{"id":372484,"date":"2024-05-21T05:13:20","date_gmt":"2024-05-21T05:13:20","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=372484"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2024-05-21T05:13:20","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=372484","title":{"rendered":"<span>\u041f\u0438\u0448\u0435\u043c \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440 \u043d\u0430 Rust \u0441 GUI<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0417\u0430\u0447\u0435\u043c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440? \u0414\u0430 \u043d\u0435\u0437\u0430\u0447\u0435\u043c, \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u0430\u043a \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u043b\u044f \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u044f GUI-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438.<\/p>\n<p>\u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u044f \u0445\u043e\u0442\u0435\u043b \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u043a\u0440\u0435\u0439\u0442\u044b, \u043a\u0430\u043a GPUI, Floem \u0438 Xilem, \u043d\u043e \u043f\u0435\u0440\u0432\u0430\u044f, \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u043f\u043e\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0434 MacOS \u0438 Linux, \u0432\u0442\u043e\u0440\u0430\u044f \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u043a\u043e\u043d\u043a\u0443 \u043e\u043a\u043d\u0443 \u0438 \u043a\u0443\u0448\u0430\u0435\u0442 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u044b \u043f\u043e\u0431\u043e\u043b\u044c\u0448\u0435 Webview \u0432 Tauri, \u0430 \u0434\u043e \u0442\u0440\u0435\u0442\u044c\u0435\u0439 \u044f \u0442\u0430\u043a \u0438 \u043d\u0435 \u0434\u043e\u0431\u0440\u0430\u043b\u0441\u044f, \u0443\u0437\u043d\u0430\u0432 \u043e\u0431 Slint.<\/p>\n<p>\u041e\u0431 Slint \u0435\u0441\u0442\u044c \u0432\u0441\u0435\u0433\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u043e\u0441\u0442\u043d\u044b\u0445 \u043f\u043e\u0441\u0442\u043e\u0432 \u043d\u0430 \u0425\u0430\u0431\u0440\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u0447\u0442\u043e \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0435.<\/p>\n<h2>\u041e\u0431 Slint<\/h2>\n<p>Slint &#8212; \u044d\u0442\u043e GUI-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u043f\u043e \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u0438\u044f\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0432\u043e\u0435\u0439 \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u043e\u0441\u0442\u044c\u044e \u0438 \u043b\u0435\u0433\u043a\u043e\u0441\u0442\u044c\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f. \u0421\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u044f\u0441\u044c \u0441 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u0430\u043c\u0438, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 Slint \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u044e\u0442, \u0447\u0442\u043e \u0438\u0445 \u0440\u0430\u043d\u0442\u0430\u0439\u043c \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0432\u0441\u0435\u0433\u043e 300 \u043a\u0431 \u0432 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0435\u0433\u043e \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u044b\u043c \u0432\u044b\u0431\u043e\u0440\u043e\u043c \u0434\u043b\u044f embedded-\u0441\u0438\u0441\u0442\u0435\u043c.<\/p>\n<p>\u0424\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 Rust, C++ \u0438 Node.js, \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 DSL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0442\u0435\u043c \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432 \u0438 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b. DSL \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0437 \u0441\u0435\u0431\u044f \u043d\u0435\u043a\u0443\u044e \u0441\u043c\u0435\u0441\u044c CSS \u0438 SwiftUI, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0438\u0436\u0435.<\/p>\n<p>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 <a href=\"https:\/\/slint.dev\/get-started#integrate-with-ides\" rel=\"noopener noreferrer nofollow\">\u043f\u043b\u0430\u0433\u0438\u043d\u044b<\/a> \u0434\u043b\u044f \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0438 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c IDE \u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u043e\u0432 \u043a\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0430\u0451\u0442 \u043d\u0430\u043c \u0449\u0435\u043f\u043e\u0442\u043a\u0443 intellisense \u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043a\u0440\u0438\u0432\u043e\u0439 \u043f\u0440\u0435\u0432\u044c\u044e, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 <code>default-font-*<\/code>. \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043a \u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043a\u0430\u0442\u0438\u0442\u044c \u0435\u0449\u0451 <a href=\"https:\/\/codeium.com\/\" rel=\"noopener noreferrer nofollow\">Codeium<\/a>, \u0443 \u043d\u0438\u0445 \u0435\u0441\u0442\u044c \u0431\u0435\u0442\u0430-\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 Slint DSL (\u0445\u043e\u0442\u044f \u043d\u0430 \u0447\u0443\u0434\u043e \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e).<\/p>\n<p>Slint \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u044f\u043c\u0438.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/44c\/660\/a87\/44c660a87423fb2d16b4a94b5d263d2e.png\" alt=\"\" title=\"\" width=\"1150\" height=\"344\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/44c\/660\/a87\/44c660a87423fb2d16b4a94b5d263d2e.png\"\/><\/figure>\n<h2>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u0440\u043e\u0435\u043a\u0442<\/h2>\n<p>\u0414\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u043c\u0430\u043b\u043e \u0437\u043d\u0430\u043a\u043e\u043c \u0441 Rust, \u0431\u0443\u0434\u0443 \u0432\u0441\u0451 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c (\u043d\u0443, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c-\u0442\u043e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u044f\u0437\u044b\u043a\u0430, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0438 \u0431\u0435\u0437 \u043c\u0435\u043d\u044f \u0441\u043c\u043e\u0436\u0435\u0442\u0435, \u0434\u0430? \u0414\u0430, \u0432\u0435\u0434\u044c?&#8230;). \u041f\u043e\u044d\u0442\u043e\u043c\u0443&#8230; \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u0440\u043e\u0435\u043a\u0442! \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u043c\u0438:<\/p>\n<pre><code class=\"powershell\">cargo new # \u0438\u043b\u0438 cargo init<\/code><\/pre>\n<p>\u041f\u043e \u0441\u0443\u0442\u0438, \u043e\u0431\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u0435\u043b\u0430\u044e\u0442 \u043e\u0434\u043d\u043e \u0438 \u0442\u043e \u0436\u0435, \u043d\u043e \u0434\u043b\u044f <code>cargo new<\/code> \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043c\u044f \u043d\u043e\u0432\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438. \u041d\u043e \u0435\u0441\u043b\u0438 \u0434\u043b\u044f <code>cargo init<\/code> \u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435, \u043e\u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u043f\u0440\u043e\u0435\u043a\u0442 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438.<\/p>\n<blockquote>\n<p>\u0415\u0441\u043b\u0438 \u0412\u0430\u043c \u043d\u0435\u00a0\u043d\u0443\u0436\u0435\u043d \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043f\u0440\u0438\u00a0\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0441\u0442\u043e\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u043b\u0430\u0433 <code>--vcs none<\/code>.<\/p>\n<\/blockquote>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0435\u043a\u0442 \u0431\u0443\u0434\u0435\u0442 \u043d\u043e\u0441\u0438\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 <code>calc-rs<\/code>. \u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0432\u0448\u0438\u0441\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442 \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b36\/54b\/cf3\/b3654bcf3f4f39d64119b449e68c7fcf.png\" alt=\"\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\" title=\"\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\" width=\"256\" height=\"146\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b36\/54b\/cf3\/b3654bcf3f4f39d64119b449e68c7fcf.png\"\/><\/p>\n<div><figcaption>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<h2>\u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h2>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d <code>cargo-edit<\/code>. \u041f\u043b\u0430\u0433\u0438\u043d \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439:<\/p>\n<pre><code class=\"powershell\">cargo install cargo-edit<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"powershell\">cargo add slint                                            # GUI cargo add --build slint-build                              # \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 DSL<\/code><\/pre>\n<h2>Slint, \u0438\u043b\u0438 \u043f\u0440\u0430\u0432\u043e\u0441\u043b\u0430\u0432\u043d\u044b\u0439 GUI<\/h2>\n<p>Slint \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 DSL. \u0415\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043c\u0430\u043a\u0440\u043e\u0441 <code>slint::slint!<\/code>. \u0418 \u044d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0443\u0434\u043e\u0431\u043d\u043e, \u0432\u0435\u0434\u044c \u043c\u043e\u0436\u043d\u043e \u0432 \u043e\u0434\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0438 \u043b\u043e\u0433\u0438\u043a\u0443, \u0438 \u0441\u0442\u0438\u043b\u0438. \u041e\u0434\u043d\u0430\u043a\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0439 \u0441 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0444\u0430\u0439\u043b\u0430\u043c\u0438.<\/p>\n<blockquote>\n<p>A\u00a0<strong>domain-specific language<\/strong>\u00a0(<strong>DSL<\/strong>) is a\u00a0computer language\u00a0specialized to a particular application\u00a0domain. This is in contrast to a\u00a0general-purpose language\u00a0(GPL), which is broadly applicable across domains. <\/p>\n<p>\u0418\u043b\u0438 \u043f\u043e \u043d\u0430\u0448\u0435\u043d\u0441\u043a\u0438:<\/p>\n<p>\u041f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u044f\u0437\u044b\u043a (DSL) &#8212; \u044d\u0442\u043e \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043d\u044b\u0439 \u044f\u0437\u044b\u043a, \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043f\u0440\u0438\u043a\u043b\u0430\u0434\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u044f\u0437\u044b\u043a\u0430 \u043e\u0431\u0449\u0435\u0433\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f (GPL), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0448\u0438\u0440\u043e\u043a\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u043e\u0431\u043b\u0430\u0441\u0442\u044f\u0445.<\/p>\n<p>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a: <a href=\"https:\/\/en.wikipedia.org\/wiki\/Domain-specific_language\" rel=\"noopener noreferrer nofollow\">wikipedia.org<\/a>. \u0421\u0442\u0430\u0442\u044c\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0438\u0441\u0447\u0435\u0440\u043f\u044b\u0432\u0430\u044e\u0449\u0430\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435 \u043d\u0430\u0434\u043e \u0432 \u043c\u0435\u043d\u044f \u0442\u0430\u043f\u043a\u0430\u043c\u0438 \u043a\u0438\u0434\u0430\u0442\u044c \u0437\u0430 \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0432\u0438\u043a\u0438.<\/p>\n<\/blockquote>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0430\u043f\u043a\u0443 <code>components<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b <code>app.slint<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u0447\u0451\u0442\u0447\u0438\u043a.<\/p>\n<pre><code class=\"rust\">import { VerticalBox, HorizontalBox, Button } from \"std-widgets.slint\"; export component AppWindow inherits Window {     in property &lt;string> window_title;      width: 400px;     height: 500px;     title: window_title;     default-font-size: 20px;      property &lt;int> count: 0;      VerticalBox {         alignment: center;              Text {             font-size: 30px;             horizontal-alignment: center;             text: \"Count: \" + count;         }         HorizontalBox {             Button {                 text: \"add\";                 clicked => {                     root.count += 1;                 }             }             Button {                 text: \"subtract\";                 clicked => {                     if root.count != 0 {                         root.count -= 1;                     }                 }             }         }     } }<\/code><\/pre>\n<blockquote>\n<p>\u0414\u043b\u044f \u0432\u0451\u0440\u0441\u0442\u043a\u0438 \u0435\u0441\u0442\u044c \u0442\u0430\u043a\u0438\u0435 layout, \u043a\u0430\u043a <code>VerticalLayout<\/code>, <code>HorizontalLayout<\/code> \u0438 <code>GridLayout<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0430. \u0418 \u0432\u044b \u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f <code>VerticalBox<\/code> \u0438 <code>HorizontalBox<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0438\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432. \u0412\u0441\u044f \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043f\u0440\u0435\u0434\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b \u043e\u0442\u0441\u0442\u0443\u043f\u044b \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u043e\u043c \u043f\u043e \u0442\u0438\u043f\u0443 \u0442\u0435\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0431-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e <a href=\"https:\/\/code.mu\/ru\/markup\/book\/supreme\/cross-browser-compatibility\/reset\/\" rel=\"noopener noreferrer nofollow\">\u043e\u0431\u043d\u0443\u043b\u044f\u044e\u0442<\/a>.  <\/p>\n<\/blockquote>\n<p>\u0412 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0444\u0430\u0439\u043b <code>build.rs<\/code>, \u044f\u0432\u043b\u044f\u044e\u0449\u0438\u0439\u0441\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u043c \u0441\u0431\u043e\u0440\u043a\u0438, \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043d\u0435\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>main<\/code> \u0441 \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>compile<\/code>. \u0422\u0435\u043f\u0435\u0440\u044c <code>app.slint<\/code> \u2013 \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430, \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c. \u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442 DSL \u0432 \u043a\u043e\u0434 Rust. \u0422\u043e \u0435\u0441\u0442\u044c \u0440\u0430\u043d\u0435\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 AppWindow \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d \u0432 <code>struct AppWindow<\/code>.<\/p>\n<pre><code class=\"rust\">fn main() {     slint_build::compile(\"components\/app.slint\").unwrap(); }<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043c\u0430\u043a\u0440\u043e\u0441 <code>slint::include_modules!()<\/code> \u0432 \u0444\u0430\u0439\u043b\u0435 <code>src\/main.rs<\/code> \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u0435\u043c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043d\u0430\u0448\u0435\u0433\u043e <code>AppWindow<\/code>.<\/p>\n<pre><code class=\"rust\">use slint::SharedString;  slint::include_modules!();  fn main() -> Result&lt;(), Box&lt;dyn std::error::Error>> {     let app = AppWindow::new()?;     app.set_window_title(SharedString::from(\"Counter\"));     app.run()?;      Ok(()) }<\/code><\/pre>\n<p>\u041c\u0435\u0442\u043e\u0434 <code>set_window_title<\/code> \u0431\u044b\u043b \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u0438\u0437 <code>in property window_title<\/code>, \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0432 \u0444\u0430\u0439\u043b\u0435 <code>components\/app.slint<\/code>. \u0421\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 <code>in<\/code> \u0434\u0435\u043b\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>windows_title<\/code>, \u0438 \u0435\u0441\u043b\u0438 \u0435\u0433\u043e \u0443\u0431\u0440\u0430\u0442\u044c, \u0442\u043e \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0441\u0447\u0438\u0442\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u043c \u0438 \u043c\u0435\u0442\u043e\u0434 <code>set_window_title<\/code>, \u043a\u0430\u043a \u0438 \u043c\u0435\u0442\u043e\u0434 <code>get_window_title<\/code>, \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d. \u0412\u044b\u0434\u0435\u0440\u0436\u043a\u0430 \u0438\u0437 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043d\u0430 \u0441\u0447\u0451\u0442 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u0430:<\/p>\n<blockquote>\n<p>\u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u043a \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a \u044d\u0442\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043e \u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u0444\u0430\u0439\u043b:<\/p>\n<p><strong>private<\/strong> (\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e): \u0414\u043e\u0441\u0442\u0443\u043f \u043a \u044d\u0442\u043e\u043c\u0443 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0443 \u0432\u043e\u0437\u043c\u043e\u0436\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0437 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<p><strong>in<\/strong>: \u0421\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0445\u043e\u0434\u043d\u044b\u043c. \u041e\u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0440\u0438\u0432\u044f\u0437\u043e\u043a \u0438\u043b\u0438 \u043f\u0443\u0442\u0435\u043c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043e\u0431\u0440\u0430\u0442\u043d\u044b\u0445 \u0432\u044b\u0437\u043e\u0432\u0430\u0445. \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u043d\u043e \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0435\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<p><strong>out<\/strong>: \u0412\u044b\u0445\u043e\u0434\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c. \u041e\u043d\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432.<\/p>\n<p><strong>in-out<\/strong>: \u042d\u0442\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043e \u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043e \u043a\u0435\u043c \u0443\u0433\u043e\u0434\u043d\u043e.<\/p>\n<p>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a: <a href=\"https:\/\/releases.slint.dev\/1.5.1\/docs\/slint\/src\/language\/syntax\/properties#properties\" rel=\"noopener noreferrer nofollow\">slint.dev<\/a>.<\/p>\n<p>\u041d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u043f\u043e\u043d\u044f\u043b \u0441\u043c\u044b\u0441\u043b \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430 <strong>in-out<\/strong>, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c <strong>in<\/strong>, \u0434\u0435\u043b\u0430\u044e\u0449\u0438\u0439 \u0440\u043e\u0432\u043d\u043e \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0ca0_\u0cb0\u0cc3. \u041f\u0440\u043e\u0448\u0443 \u0437\u043d\u0430\u044e\u0449\u0438\u0445 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u043e\u0431 \u044d\u0442\u043e\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435.<\/p>\n<\/blockquote>\n<p><code>cargo run<\/code> \u2013 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043d\u0430\u0448 \u0441\u0447\u0451\u0442\u0447\u0438\u043a-\u043d\u0435\u0434\u043e\u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/127\/79b\/12b\/12779b12b4c1e6a11e2d308454169448.png\" alt=\"&quot;Wake the F*** up,\u00a0Samurai.\u00a0We have a city to burn.&quot;\" title=\"&quot;Wake the F*** up,\u00a0Samurai.\u00a0We have a city to burn.&quot;\" width=\"402\" height=\"532\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/127\/79b\/12b\/12779b12b4c1e6a11e2d308454169448.png\"\/><\/p>\n<div><figcaption>&#171;Wake the F*** up,\u00a0Samurai<em>.<\/em>\u00a0We have a city to burn.&#187;<\/figcaption><\/div>\n<\/figure>\n<blockquote>\n<p>\u0417\u0430\u0431\u0430\u0432\u043d\u043e \u0442\u043e, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u043d\u0430\u0436\u0430\u043b\u0438 Tab, \u0442\u043e \u0432\u0440\u044f\u0434 \u043b\u0438 \u0443\u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0441\u043d\u044f\u0442\u044c \u0444\u043e\u043a\u0443\u0441 \u0441 \u043a\u043d\u043e\u043f\u043e\u043a \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f (\u3186_\u3186).<\/p>\n<\/blockquote>\n<h2>\u041c\u0443\u043b\u044c\u0442\u0438\u044f\u0437\u044b\u0447\u043d\u043e\u0441\u0442\u044c<\/h2>\n<p>Slint \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u043d\u0430\u0446\u0438\u043e\u043d\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <a href=\"https:\/\/www.gnu.org\/software\/gettext\/\" rel=\"noopener noreferrer nofollow\">Gettext<\/a> \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/releases.slint.dev\/1.5.1\/docs\/slint\/src\/language\/concepts\/translations\" rel=\"noopener noreferrer nofollow\">\u043c\u0430\u043a\u0440\u043e\u0441\u044b<\/a>, \u0447\u0442\u043e, \u043a\u0430\u043a \u043f\u043e-\u043c\u043d\u0435, \u0442\u0430\u043a\u043e\u0435 \u0441\u0435\u0431\u0435. \u041f\u043e\u0447\u0435\u043c\u0443? \u2013 \u044f \u0447\u0430\u0441\u0430 \u0442\u0440\u0438 \u043f\u044b\u0442\u0430\u043b\u0441\u044f \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u043d\u043e \u044f \u0442\u0430\u043a \u0438 \u043d\u0435 \u043f\u043e\u043d\u044f\u043b, \u043f\u043e\u0447\u0435\u043c\u0443 \u043d\u0438 \u044d\u0442\u043e\u0442 \u043c\u043e\u0434\u0443\u043b\u044c, \u043d\u0438 \u043c\u043e\u0434\u0443\u043b\u044c \u043b\u043e\u0433\u043e\u0432 Slint \u0442\u0430\u043a \u0438 \u043d\u0435 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438, \u0430 \u0432 \u0434\u043e\u043a\u0430\u0445 \u0447\u0443\u0442\u044c \u043b\u0438 \u043d\u0435 \u043f\u0430\u0440\u0443 \u0441\u043b\u043e\u0432 \u043e \u043d\u0438\u0445 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e (\u256f\u00b0\u25a1\u00b0\uff09\u256f\ufe35 \u253b\u2501\u253b. \u0415\u0441\u043b\u0438 \u043a\u043e\u043c\u0443 \u0431\u0443\u0434\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u0441\u043e\u0445\u0440\u0430\u043d\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u0441 gettext \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 <a href=\"https:\/\/gitverse.ru\/ertanic\/calc-rs\/content\/counter-gettext\" rel=\"noopener noreferrer nofollow\">\u0432\u0435\u0442\u043a\u0435<\/a> \u0440\u0435\u043f\u044b.<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/projectfluent.org\/\" rel=\"noopener noreferrer nofollow\">Fluent<\/a> \u043e\u0442 Mozilla (\u25cf&#8217;\u25e1&#8217;\u25cf). Fluent \u2013 \u0434\u0440\u0443\u0433\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0443\u0441\u0442\u0440\u0430\u043d\u044f\u044e\u0449\u0430\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441\u0432\u043e\u0435\u0433\u043e \u043f\u0440\u0435\u0434\u0448\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u0438\u043a\u0430 gettext. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0437 \u044d\u0442\u0438\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c:<\/p>\n<ol>\n<li>\n<p><strong>\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f.<\/strong>\u00a0\u0412 gettext \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u0445\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 (\u043e\u0431\u044b\u0447\u043d\u043e \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c) \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430. \u042d\u0442\u043e \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u0432\u044b\u043d\u0443\u0436\u0434\u0430\u044f \u0438\u0445 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u044d\u0442\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u043e\u0432.<\/p>\n<\/li>\n<\/ol>\n<ol start=\"2\">\n<li>\n<p><strong>\u0412\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439.<\/strong>\u00a0Gettext \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043d\u0430\u0431\u043e\u0440 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u043d\u0430\u0446\u0438\u043e\u043d\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438 \u2014 \u0434\u043b\u044f \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0447\u0438\u0441\u0435\u043b. Fluent \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044e \u0432\u0430\u0440\u0438\u0430\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u0441\u0442\u0440\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441 \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u0430\u043c\u0438.<\/p>\n<\/li>\n<\/ol>\n<ol start=\"3\">\n<li>\n<p><strong>\u0412\u043d\u0435\u0448\u043d\u0438\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b.<\/strong>\u00a0Gettext \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b, \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f \u0437\u0430\u0434\u0430\u0442\u044c \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u2014 \u0447\u0438\u0441\u0435\u043b, \u0434\u0430\u0442. Fluent \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u0430\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0442\u043e\u0447\u043d\u044b\u0435 \u0442\u0435\u043a\u0441\u0442\u044b \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432.<\/p>\n<\/li>\n<\/ol>\n<ol start=\"4\">\n<li>\n<p><strong>\u0410\u043d\u043d\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430.<\/strong>\u00a0Gettext \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0432\u0441\u0435 \u0442\u0440\u0438 \u0443\u0440\u043e\u0432\u043d\u044f \u0432 \u043e\u0434\u043d\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u043d\u0435\u0447\u0451\u0442\u043a\u043e\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435 (fuzzy). \u0412\u043e Fluent \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0434\u0432\u0430 \u0438\u0437 \u044d\u0442\u0438\u0445 \u0443\u0440\u043e\u0432\u043d\u0435\u0439 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043e\u0442 \u0442\u0440\u0435\u0442\u044c\u0435\u0433\u043e.<\/p>\n<\/li>\n<\/ol>\n<ol start=\"5\">\n<li>\n<p><strong>\u0424\u043e\u0440\u043c\u0430\u0442 \u0434\u0430\u043d\u043d\u044b\u0445.<\/strong>\u00a0Gettext \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0442\u0440\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 \u2014 *.po, *.pot \u0438 *.mo. Fluent \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0435\u0434\u0438\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0444\u0430\u0439\u043b\u0430 *.ftl, \u0447\u0442\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 \u0438 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0448\u0430\u0433\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u0440\u0430\u0441\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044e \u0432 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a: <a href=\"https:\/\/github.com\/projectfluent\/fluent\/wiki\/Fluent-vs-gettext\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 Fluent Project<\/a>.<\/p>\n<\/li>\n<\/ol>\n<blockquote>\n<p>\u041c\u0435\u043c \u043e\u0442\u0442\u0443\u0434\u0430 \u0436\u0435:<\/p>\n<p>Gettext \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 UTF-8. \u0412 \u0446\u0435\u043b\u043e\u043c, \u043d\u0430 \u044d\u0442\u043e\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 Unicode \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f.  <\/p>\n<\/blockquote>\n<p>\u0425\u043e\u0442\u044f Fluent \u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u0440\u0443\u0447\u0435 \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u043e\u0432 (\u0441\u043e\u0437\u0434\u0430\u043b \u043d\u0443\u0436\u043d\u044b\u0439 \u0444\u0430\u0439\u043b\u0438\u043a \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0448\u044c, \u0431\u0435\u0437 \u043d\u0430\u0434\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u0432 \u0440\u0430\u0437\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c), \u043d\u043e \u0432\u043e\u0442 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u0440\u0435\u0439\u0442\u044b \u043e\u0442 Fluent Project \u2013 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u044b\u0440\u0430\u044f \u0448\u043b\u044f\u043f\u0430. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043a\u043e\u0441\u0442\u044b\u043b\u0438 \u0431\u0435\u0437 \u0438\u0437\u043b\u0438\u0448\u0435\u0441\u0442\u0432 (\u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u044c, \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043b\u043e\u043a\u0430\u043b\u0435\u0439, \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a \u0438 \u0442.\u043f.).<\/p>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041d\u043e\u0432\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<pre><code class=\"powershell\">cargo add thiserror fluent sys-locale unic-langid cargo add --build copy_to_output<\/code><\/pre>\n<p><strong>src\/file.rs<\/strong>:<\/p>\n<pre><code class=\"rust\">use std::{env, path::{Path, PathBuf}};  use thiserror::Error;  #[derive(Error, Debug)] pub enum FileReadError {     #[error(\"Unable to read file: {0}\")]     ReadError(String, String),     #[error(\"Unable to read file as UTF-8\")]     Utf8Error }  \/\/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u043a \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 pub fn get_dir_path&lt;T: AsRef&lt;Path>>(subfolder: T) -> PathBuf {     let folder = subfolder.as_ref();     get_root_dir().join(folder) }  \/\/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u043a \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0439 \u0444\u0430\u0439\u043b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b pub fn get_root_dir() -> PathBuf {     env::current_exe()         .expect(\"Unable to get a exe path.\")         .parent()         .expect(\"Unable to get a root folder.\")         .into() }  \/\/\/ \u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 pub fn get_file_text(path: impl AsRef&lt;Path>) -> Result&lt;String, FileReadError> {     let buf = match std::fs::read(&amp;path) {         Ok(buf) => buf,         Err(e) => return Err(FileReadError::ReadError(path.as_ref().to_string_lossy().into_owned(), e.to_string()))     };      let text = match String::from_utf8(buf) {         Ok(text) => text,         Err(_) => return Err(FileReadError::Utf8Error)     };      Ok(text) }  pub fn file_exists(path: impl AsRef&lt;Path>) -> bool {     std::fs::metadata(path).is_ok() }<\/code><\/pre>\n<p><strong>src\/fluent.rs<\/strong>:<\/p>\n<pre><code class=\"rust\">use std::{fmt::Debug, rc::Rc}; use fluent::{FluentArgs, FluentBundle, FluentResource};  use crate::file::{file_exists, get_file_text};  #[derive(thiserror::Error, Debug)] pub enum FluentError {     #[error(\"Unable to read FTL file: {0}\")]     UnableReadFtlError(#[from] crate::file::FileReadError),      #[error(\"Fluent syntax error\")]     FluentSyntaxError,      #[error(\"Message by key {0} not found\")]     MessageNotFoundError(String) }  #[inline] pub fn get_locale() -> String {     if let Some(locale) = sys_locale::get_locale() {         locale     } else {         default_locale()     } }  #[inline] fn default_locale() -> String {     \"en-US\".to_string() }  pub fn get_msg(bundle: &amp;Bundle, key: impl AsRef&lt;str>+Debug, args: Option&lt;&amp;FluentArgs>) -> Result&lt;String, FluentError> {     let key = key.as_ref();      if let Some(fluent_msg) = bundle.get_message(key) {         if let Some(pattern) = fluent_msg.value() {             let mut errors = Vec::new();             let msg = bundle.format_pattern(pattern, args, &amp;mut errors);                          for e in errors {                 eprintln!(\"{}\", e);             }                          Ok(msg.into_owned())         } else {             Err(FluentError::MessageNotFoundError(key.to_string()))         }     } else {         Err(FluentError::MessageNotFoundError(key.to_string()))     } }  type Bundle = FluentBundle&lt;FluentResource>; pub fn load_locale(locale: impl AsRef&lt;str>+Debug) -> Result&lt;Rc&lt;Bundle>, FluentError> {     let locale = locale.as_ref();     let resource = create_resource(&amp;locale)?;     let bundle = create_bundle(resource, locale)?;      Ok(         Rc::new(bundle)     ) }  fn create_resource(locale: impl AsRef&lt;str>+Debug) -> Result&lt;FluentResource, FluentError> {     let locale = locale.as_ref();          let lang_folder = crate::file::get_dir_path(std::path::Path::new(\"lang\"));     let file = |l: &amp;str| lang_folder.join(format!(\"{}.ftl\", l));      let map_err = |e| FluentError::from(e);     let locale_file = file(locale);     let resource = if file_exists(&amp;locale_file) {         get_file_text(locale_file).map_err(map_err)?     } else {         get_file_text(file(default_locale().as_str())).map_err(map_err)?     };      match FluentResource::try_new(resource) {         Ok(resource) => Ok(resource),         Err(_) => Err(FluentError::FluentSyntaxError)     } }  fn create_bundle(resource: FluentResource, locale: impl AsRef&lt;str>+Debug) -> Result&lt;Bundle, FluentError> {     let locale = locale.as_ref();          let langid: unic_langid::LanguageIdentifier = locale         .parse()         .map_err(|_| FluentError::FluentSyntaxError)?;     let mut bundle = FluentBundle::new(vec![langid]);          match bundle.add_resource(resource) {         Ok(_) => Ok(bundle),         Err(_) => Err(FluentError::FluentSyntaxError)     } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0424\u0430\u0439\u043b\u044b \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u0443\u0434\u0443\u0442 \u043b\u0435\u0436\u0430\u0442\u044c \u0432 \u043f\u0430\u043f\u043e\u0447\u043a\u0435 <code>lang<\/code> \u0440\u044f\u0434\u043e\u043c \u0441 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u043c \u0444\u0430\u0439\u043b\u043e\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b. \u0414\u043b\u044f \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0430\u043f\u043a\u0438 \u0432 \u043f\u0430\u043f\u043a\u0443 \u0441 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430\u043c\u0438 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043a\u0440\u0435\u0439\u0442 <a href=\"https:\/\/crates.io\/crates\/copy_to_output\" rel=\"noopener noreferrer nofollow\">copy_to_output<\/a>.<\/p>\n<pre><code class=\"powershell\">cargo add --build copy_to_output<\/code><\/pre>\n<pre><code class=\"rust\">\/\/ build.rs use std::env; use copy_to_output::copy_to_output;  fn main() {     copy_to_output(\"lang\", &amp;env::var(\"PROFILE\").unwrap()).unwrap();          slint_build::compile(\"components\/app.slint\").unwrap(); }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u0424\u0430\u0439\u043b\u044b \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/summary>\n<div class=\"spoiler__content\">\n<p><strong>lang\/ru-RU.ftl<\/strong><\/p>\n<pre><code class=\"fsharp\">app-name = \u0421\u0447\u0451\u0442\u0447\u0438\u043a  counter-count =      { $count ->         [0] \u041d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u043e\u0447\u043a\u0430         [one] {$count} \u043e\u0447\u043a\u043e         [few] {$count} \u043e\u0447\u043a\u0430         *[other] {$count} \u043e\u0447\u043a\u043e\u0432     }  counter-add = \u041f\u0440\u0438\u0431\u0430\u0432\u0438\u0442\u044c counter-subtract = \u0423\u0431\u0430\u0432\u0438\u0442\u044c<\/code><\/pre>\n<p><strong>lang\/en-US.ftl<\/strong><\/p>\n<pre><code class=\"fsharp\">app-name = Counter  counter-count =      {$count ->          [0] You have no points         [one] You have one point         *[other] You have {$count} points     }  counter-add = Add counter-subtract = Subtract<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041f\u0440\u043e\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0442\u044c \u044d\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 DSL \u0431\u0443\u0434\u0435\u043c \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/releases.slint.dev\/1.5.1\/docs\/slint\/src\/language\/syntax\/globals\" rel=\"noopener noreferrer nofollow\">global singleton<\/a> \u0438 pure callback. \u0414\u0430 \u0432\u043e\u043e\u0431\u0449\u0435 \u043c\u043d\u043e\u0433\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0432 \u043f\u043b\u044e\u0441-\u043c\u0438\u043d\u0443\u0441 \u043a\u0440\u0443\u043f\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043f\u0440\u043e\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 global singleton, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0445\u043e\u0442\u0438\u0442\u0435 \u0432\u0435\u0441\u0442\u0438 \u043e\u0433\u0440\u043e\u043c\u043d\u0443\u044e \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0438\u0437 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043e\u0442 \u0441\u0432\u043e\u0435\u0433\u043e \u0434\u043e \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0442\u0440\u0435\u0439\u0442 <code>Window<\/code>.<\/p>\n<blockquote>\n<p><em>\u0427\u0438\u0441\u0442\u044b\u0439<\/em> \u043a\u043e\u043b\u043b\u0431\u044d\u043a, \u0438\u043b\u0438 <em>pure<\/em> callback \u2013 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u0434\u0430\u044e\u0449\u0438\u0439 \u0434\u0430\u0442\u044c \u043f\u043e\u043d\u044f\u0442\u044c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0443 \u0442\u043e, \u0447\u0442\u043e \u043a\u043e\u043b\u043b\u0431\u044d\u043a \u043d\u0435 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439, \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0438\u043a\u0430\u043a\u0438\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u0440\u0438 \u0435\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0435 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0441\u0430\u043c \u043c\u043e\u0436\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c, \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u043e\u043d\u0438 \u0438\u043b\u0438 \u043d\u0435\u0442.<\/p>\n<p>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a: <a href=\"https:\/\/releases.slint.dev\/1.5.1\/docs\/slint\/src\/language\/concepts\/purity\" rel=\"noopener noreferrer nofollow\">slint.dev<\/a>.<\/p>\n<\/blockquote>\n<p>\u0414\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0435\u0439 \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e\u0441\u0442\u0438 \u043e\u0442\u043b\u0435\u043f\u0438\u043c \u0432\u0441\u044e \u0432\u0451\u0440\u0441\u0442\u043a\u0443 \u043e\u0442 <code>AppWindow<\/code>, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b <code>components\/counter.slint<\/code> \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 <code>Counter<\/code>.<\/p>\n<pre><code class=\"rust\">import { VerticalBox, HorizontalBox, Button } from \"std-widgets.slint\";  export component Counter {     property &lt;int> count: 0;      VerticalBox {         alignment: center;              Text {             font-size: 30px;             horizontal-alignment: center;             text: \"Count: \" + count;         }         HorizontalBox {             Button {                 text: \"add\";                 clicked => {                     root.count += 1;                 }             }             Button {                 text: \"subtract\";                 clicked => {                     if root.count != 0 {                         root.count -= 1;                     }                 }             }         }     } }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b <code>components\/globals.slint<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043f\u0438\u0448\u0435\u043c \u0441\u0438\u043d\u0433\u043b\u0442\u043e\u043d Fluent \u0441 \u043a\u043e\u043b\u043b\u0431\u044d\u043a\u043e\u043c <code>message<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u043a\u043b\u044e\u0447 \u0434\u043b\u044f fluent-\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u0438 \u043a\u043e\u043b\u043b\u0431\u044d\u043a param-message, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a \u0436\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043a\u043b\u044e\u0447 \u0438 \u043c\u0430\u0441\u0441\u0438\u0432 (\u0430-\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u044c) \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432. \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0432 \u0432\u0438\u0434\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 (\u0434\u0430-\u0434\u0430, \u043c\u043e\u0436\u043d\u043e \u0434\u0430\u0436\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c).<\/p>\n<pre><code class=\"rust\">export struct MessageParam {     name: string,     value: string }  export global Fluent {     pure callback message(string) -> string;     pure callback param-message(string, [MessageParam]) -> string; }<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435, \u0447\u0442\u043e\u0431\u044b <code>Fluent<\/code> \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0431\u044b\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432 \u0440\u0430\u0441\u0442-\u043a\u043e\u0434\u0435, \u0432 <code>components\/app.slint<\/code> (\u0438\u043b\u0438 \u0432 \u043b\u044e\u0431\u043e\u0439 \u0442\u043e\u0447\u043a\u0435 \u0432\u0445\u043e\u0434\u0430) \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c <code>Fluent<\/code> \u0438 \u0441\u043d\u043e\u0432\u0430 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c ( \u0c20 \u035f\u0296 \u0c20). \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 <code>MessageParam<\/code> \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0441\u0430\u043c \u043f\u043e\u0434\u0442\u044f\u0433\u0438\u0432\u0430\u0435\u0442, \u0432\u0438\u0434\u044f \u0435\u0451 \u0432 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u0445 \u043a\u043e\u043b\u043b\u0431\u044d\u043a\u0430. \u041d\u0430\u0432\u0435\u0440\u043d\u043e\u0435 \u00af\\_(\u30c4)_\/\u00af.<\/p>\n<pre><code class=\"rust\">\/\/ components\/app.slint import { Fluent } from \"globals.slint\"; export { Fluent }<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0438 \u0434\u043b\u044f \u043a\u043e\u043b\u043b\u0431\u044d\u043a\u0430, \u043d\u0443\u0436\u043d\u043e \u0432 <code>src\/main.rs<\/code> \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 <code>Fluent<\/code> \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0435\u043c\u0443 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043d\u0430 \u043a\u043e\u043b\u043b\u0431\u044d\u043a \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0442\u043e\u0434 <code>on_{\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043b\u043b\u0431\u044d\u043a\u0430}<\/code>.<\/p>\n<pre><code class=\"rust\">let app = AppWindow::new()?;  let fluent = app.global::&lt;Fluent>(); let b = bundle.clone(); fluent.on_message(move |key| {     match get_msg(&amp;b, &amp;key, None) {         Ok(msg) => SharedString::from(msg),         Err(_) => key     } }); fluent.on_param_message(move |key, args| {     let args = FluentArgs::from_iter(         args         .iter()         .map(|a| (a.name.to_string(), FluentValue::try_number(a.value.to_string())))     );      match get_msg(&amp;bundle, &amp;key, Some(&amp;args)) {         Ok(msg) => SharedString::from(msg),         Err(_) => key     } });  app.run()?;<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u0435\u043c \u0443\u0431\u0440\u0430\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>window_title<\/code> \u0438 \u043a\u043e\u0434 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 <code>AppWindow<\/code> \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u0448\u0438\u043c \u043c\u043e\u0434\u0443\u043b\u0435\u043c <code>Fluent<\/code>. \u0422\u043e\u0447\u043d\u043e \u0442\u0430\u043a \u0436\u0435 \u0438 \u0441 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c <code>Counter<\/code>.<\/p>\n<pre><code class=\"rust\">\/\/ components\/counter.slint import { VerticalBox, HorizontalBox, Button } from \"std-widgets.slint\"; import { Fluent } from \"globals.slint\";  export component Counter {     property &lt;int> count: 0;     pure function get-counter-fluent() -> string {         Fluent.param-message(\"counter-count\", [{name: \"count\", value: count}] )     }     function update-counter() {         counter.text = get-counter-fluent();     }      VerticalBox {         alignment: center;              counter := Text {             font-size: 30px;             horizontal-alignment: center;             text: get-counter-fluent();         }         HorizontalBox {             Button {                 text: Fluent.message(\"counter-add\");                 clicked => {                     root.count += 1;                     update-counter();                 }             }             Button {                 text: Fluent.message(\"counter-subtract\");                 clicked => {                     if root.count != 0 {                         root.count -= 1;                         update-counter();                     }                 }             }         }     } }<\/code><\/pre>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e59\/b55\/2fc\/e59b552fc4b46daa8f32c0151c6075cf.gif\" alt=\"\u041b\u044e\u0431\u043b\u044e \u0440\u0443\u0441\u0441\u043a\u0438\u0439 \u044f\u0437\u044b\u043a, \u0445\u043e\u0442\u044f \u0431\u044b \u0437\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432 \u043d\u0435\u043c \u0435\u0441\u0442\u044c \u0433\u0435\u043d\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0444\u0440\u0430\u0437\u0430 \u00ab\u0434\u0430 \u043d\u0435\u0442 \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435\u00bb\" title=\"\u041b\u044e\u0431\u043b\u044e \u0440\u0443\u0441\u0441\u043a\u0438\u0439 \u044f\u0437\u044b\u043a, \u0445\u043e\u0442\u044f \u0431\u044b \u0437\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432 \u043d\u0435\u043c \u0435\u0441\u0442\u044c \u0433\u0435\u043d\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0444\u0440\u0430\u0437\u0430 \u00ab\u0434\u0430 \u043d\u0435\u0442 \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435\u00bb\" width=\"400\" height=\"500\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e59\/b55\/2fc\/e59b552fc4b46daa8f32c0151c6075cf.gif\"\/><\/p>\n<div><figcaption>\u041b\u044e\u0431\u043b\u044e \u0440\u0443\u0441\u0441\u043a\u0438\u0439 \u044f\u0437\u044b\u043a, \u0445\u043e\u0442\u044f \u0431\u044b \u0437\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432 \u043d\u0435\u043c \u0435\u0441\u0442\u044c \u0433\u0435\u043d\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0444\u0440\u0430\u0437\u0430 \u00ab\u0434\u0430 \u043d\u0435\u0442 \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435\u00bb<\/figcaption><\/div>\n<\/figure>\n<h2>\u0418\u043a\u043e\u043d\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b<\/h2>\n<p>\u041f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e, \u043d\u043e \u043d\u0435 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u0434\u0430\u043b\u0451\u043a\u043e. \u0410 \u0438\u043c\u0435\u043d\u043d\u043e \u0443 \u043d\u0430\u0441 \u043d\u0435\u0442 \u043d\u0430\u0448\u0435\u0439 \u0431\u0440\u0435\u043d\u0434\u043e\u0432\u043e\u0439 \u0438\u043a\u043e\u043d\u043a\u0438! \u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c. \u0418\u0449\u0435\u043c \u043d\u0430\u0448\u0443 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u0443\u044e \u0438\u043a\u043e\u043d\u043a\u0443 \u0432 png \u0438 ico \u0444\u043e\u0440\u043c\u0430\u0442\u0430\u0445 \u0438 \u0437\u0430\u043a\u0438\u0434\u044b\u0432\u0430\u0435\u043c \u0432 \u043f\u0430\u043f\u043a\u0443 <code>icons<\/code>. \u0412 \u0444\u0430\u0439\u043b\u0435 <code>components\/app.slint<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>icon<\/code> \u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u044b <code>@image-url<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0443\u0442\u044c \u0434\u043e \u043d\u0430\u0448\u0435\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<pre><code class=\"rust\">export component AppWindow inherits Window {     icon: @image-url(\"..\/icons\/icon.png\");     \/\/ &lt;...> }<\/code><\/pre>\n<p>\u0412 \u0444\u0430\u0439\u043b\u0435 <code>Cargo.toml<\/code> \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 <a href=\"https:\/\/docs.rs\/winres\/latest\/winres\/\" rel=\"noopener noreferrer nofollow\">winres<\/a>. \u041a\u0440\u0435\u0439\u0442 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0444\u0430\u0439\u043b\u044b \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u043a\u043e\u043d\u043a\u0430 \u0444\u0430\u0439\u043b\u0430 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0434 Windows.<\/p>\n<pre><code class=\"rust\">[target.'cfg(windows)'.build-dependencies] winres = \"0.1.12\"<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432 <code>build.rs<\/code> \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"rust\">if cfg!(target_os = \"windows\") {     winres::WindowsResource::new()         .set_icon(\"icons\/icon.ico\")         .compile()         .unwrap(); }<\/code><\/pre>\n<h2>\u041a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440<\/h2>\n<p>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0447\u0443\u0442\u044c \u0443\u0441\u043b\u043e\u0436\u043d\u0438\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u0432\u0451\u0440\u0441\u0442\u043a\u0438 \u0438 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u0442\u044c \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u043d\u0430\u0448 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440. \u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u043d\u0430 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0442\u043e\u0440\u0430\u0445, \u043d\u043e \u0434\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u0442\u0435\u043c\u0430 \u0434\u043b\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b <code>components\/calculator.rs<\/code> \u0441 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c <code>Calculator<\/code> (\u0442\u0435\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044c: (\u256f\u00b0\u25a1\u00b0\uff09\u256f\ufe35 \u253b\u2501\u253b). \u0412 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u043c\u0430\u0441\u0441\u0438\u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432 \u0441\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u043a\u043d\u043e\u043f\u043e\u043a.<\/p>\n<pre><code class=\"rust\">import { Button, VerticalBox, HorizontalBox } from \"std-widgets.slint\";  export component Calculator {     property &lt;[[string]]&gt; buttons: [         [\"1\", \"2\", \"3\", \"+\"],         [\"4\", \"5\", \"6\", \"-\"],         [\"7\", \"8\", \"9\", \"*\"],         [\"C\", \"0\", \"=\", \"\/\"]     ];          VerticalBox {         for row in root.buttons: HorizontalBox {             for button in row: Button {                 text: button;             }         }     } }<\/code><\/pre>\n<p>\u041f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e. \u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043e\u043b\u044f, \u043a\u0443\u0434\u0430 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0432\u0432\u043e\u0434\u0430-\u0432\u044b\u0432\u043e\u0434\u0430.<\/p>\n<pre><code class=\"rust\">VerticalBox {     VerticalBox {         Text {             text: \"0\";             font-size: 30px;             opacity: 0;             horizontal-alignment: right;             vertical-alignment: center;         }         Text {             text: \"0\";             font-size: 60px;             horizontal-alignment: right;             vertical-alignment: center;         }     }      for row in root.buttons: HorizontalBox {         for button in row: Button {             text: button;         }     } }<\/code><\/pre>\n<p>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0437\u0430\u0434\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0443, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0442\u0430\u043a\u043e\u0435, \u043a\u0430\u043a \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043f\u0440\u043e\u0448\u043b\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u0438 \u0444\u043b\u0430\u0433, \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c\u044b\u0439 \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"rust\">struct CalcState {     current-value: int,     last-value: int,     operator: string,     computed: bool }  export component Calculator {     property &lt;CalcState> state: { current-value: 0, last-value: 0, operator: \"\", computed: true };     \/\/&lt;...> }<\/code><\/pre>\n<blockquote>\n<p>\u0424\u043b\u0430\u0433 <code>computed<\/code> \u0441\u0440\u0430\u0437\u0443 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0432 <code>true<\/code>, \u0447\u0442\u043e\u0431\u044b \u0432\u0435\u0440\u0445\u043d\u0435\u0435 \u043f\u043e\u043b\u0435 \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u044b\u043c \u0434\u043e \u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u0432\u043e\u0434\u0430.<\/p>\n<\/blockquote>\n<p>\u041c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u044c <code>MathLogic<\/code>, \u0438\u043b\u0438 \u0447\u0442\u043e-\u0442\u043e \u0442\u0438\u043f\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438 \u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0439, \u043d\u043e \u044d\u0442\u043e \u0447\u0440\u0435\u0437\u043c\u0435\u0440\u043d\u043e \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0438 \u0431\u0443\u0434\u0435\u043c \u0432\u0441\u0451 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0441\u0438\u043b\u0430\u043c\u0438 Slint DSL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0438\u0442\u043e\u0433\u0435 \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d \u0432 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u0434.<\/p>\n<pre><code class=\"rust\">export component Calculator {     function get-state() -> CalcState{ { current-value: 0, last-value: 0, operator: \"\", computed: true } }     property &lt;CalcState> state: get-state();     property &lt;[[string]]&gt; buttons: [\/*&lt;..>*\/];          callback value-computed;     callback state-cleared;     callback operator-pressed(string);     callback number-pressed(int);          \/\/ \u041d\u0435 \u043a\u0438\u0434\u0430\u0439\u0442\u0435 \u0432 \u043c\u0435\u043d\u044f \u0442\u0430\u043f\u043a\u0438, \u043d\u043e \u0434\u0430, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0432 \u043a\u043e\u043b\u043b\u0431\u044d\u043a\u0430\u0445     operator-pressed(operator) => {         if (state.computed) {             state.last-value = state.current-value;             state.current-value = 0;             state.computed = false;         } else if (state.operator == \"\") {             state.last-value = state.current-value;             state.current-value = 0;         }         state.operator = operator;     }     state-cleared => {         state = get-state();     }     number-pressed(number) => {         if (state.computed) {             state.last-value = 0;             state.operator = \"\";         }          state.current-value = state.current-value * 10 + number;     }     value-computed() => {         state.computed = true;          if (state.operator == \"+\") {             state.current-value = state.last-value + state.current-value;         } else if (state.operator == \"-\") {             state.current-value = state.last-value - state.current-value;         } else if (state.operator == \"\u00d7\") {             state.current-value = state.last-value * state.current-value;         } else if (state.current-value != 0) {             state.current-value = state.last-value \/ state.current-value;         }                  state.last-value = 0;         state.operator = \"\";     }     \/\/ \u0420\u043e\u0443\u0442\u0438\u043d\u0433 \u043a\u043d\u043e\u043f\u043e\u043a     function route-actions(action: string) {         if action == \"=\" {             value-computed();         } else {             state-cleared();         }     }     function button-pressed(button: string) {         if (is-operator(button)) {             operator-pressed(button);         } else if (is-action(button)) {             route-actions(button);         } else {             number-pressed(button.to-float());         }     }          \/\/&lt;...>          pure function is-operator(button: string) -> bool {         button == \"+\"          || button == \"-\"          || button == \"*\"          || button == \"\/\"     }     pure function is-action(button: string) -> bool {         button == \"=\" || button == \"C\"     } }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0435\u043c \u0448\u0430\u0431\u043b\u043e\u043d, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0432\u044b\u0432\u043e\u0434 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0438 \u043f\u0440\u0438\u043f\u0440\u0430\u0432\u0438\u0432 \u0432\u0441\u0451 \u044d\u0442\u043e \u043a\u0430\u043f\u0435\u043b\u044c\u043a\u043e\u0439 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0439.<\/p>\n<pre><code class=\"rust\">export component Calculator {     function get-state() -> CalcState{ { current-value: 0, last-value: 0, operator: \"\", computed: true } }     property &lt;CalcState> state: get-state();      \/\/&lt;...>      VerticalBox {         VerticalBox {             Text {                 text: \"\\{state.last-value} \\{state.operator}\";                 font-size: 30px;                 opacity: 0;                 horizontal-alignment: right;                 vertical-alignment: center;                  states [                     visible when !state.computed : {                         opacity: 1;                         in {                             animate opacity { duration: 120ms; }                         }                         out {                             animate opacity { duration: 60ms; }                         }                     }                 ]             }             Text {                 text: state.current-value;                 font-size: 60px;                 horizontal-alignment: right;                 vertical-alignment: center;             }         }          for row in root.buttons: HorizontalBox {             for button in row: btn := Button {                 text: button;                 clicked => { button-pressed(btn.text) }             }         }     }      \/\/&lt;...> }<\/code><\/pre>\n<p>\u041d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u043a \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0434\u043b\u044f \u0441\u0442\u0438\u043b\u044f \u043f\u043e\u043b\u0443\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u044b\u0439 \u0444\u043e\u043d \u043e\u043a\u043d\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>Colors.rgba<\/code> \u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 <code>background<\/code> . \u0412\u043e\u043e\u0431\u0449\u0435 \u0441 \u044d\u0442\u0438\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e\u043c \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0431\u044b\u0442\u044c \u043e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u044b\u043c\u0438, \u0438\u0431\u043e \u043e\u043d\u043e \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u0441\u0442\u044c \u0443 \u0432\u0441\u0435\u0433\u043e, \u0447\u0442\u043e \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u043a\u043d\u0435 (\u25cf&#8217;\u25e1&#8217;\u25cf). \u0415\u0441\u0442\u044c \u0435\u0449\u0451 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>opacity<\/code>, \u043d\u043e \u043e\u043d\u043e \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u043e\u043a\u043d\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u043c\u0435\u0435\u043c \u0442\u043e, \u0447\u0442\u043e \u0438\u043c\u0435\u0435\u043c.<\/p>\n<pre><code class=\"rust\">import { Calculator } from \"calculator.slint\";  export component AppWindow inherits Window {     in property &lt;string> window_title;      width: 300px;     height: 500px;     title: window_title;     icon: @image-url(\"..\/icons\/icon.png\");     background: Colors.rgba(28,28,28,0.9); \/\/ &lt;-- \u0414\u0435\u043b\u0430\u0435\u043c \u043e\u043a\u043d\u043e \u0447\u0443\u0442\u044c-\u0447\u0443\u0442\u044c \u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u044b\u043c     default-font-size: 20px;          Calculator {         width: parent.width;         height: parent.height;     } }<\/code><\/pre>\n<p>\u041a\u0441\u0442\u0430\u0442\u0438, \u0435\u0441\u043b\u0438 \u044f \u0435\u0449\u0451 \u043d\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u043b, \u0442\u043e \u043a\u043e\u0433\u0434\u0430 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 <code>width<\/code> \u0438 <code>height<\/code> \u0443 \u043e\u043a\u043d\u0430, \u0442\u043e \u043e\u043d\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0451\u0442 \u0431\u044b\u0442\u044c resizable. \u0415\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u043e \u0440\u0430\u0441\u0442\u044f\u0433\u0438\u0432\u0430\u0442\u044c \u043e\u043a\u043e\u0448\u043a\u043e, \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u0438\u0431\u043e <code>min-<\/code>,<code>max-<\/code>, \u043b\u0438\u0431\u043e <code>preferred-<\/code> \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430. \u041f\u0435\u0440\u0432\u044b\u0439 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u044e\u0442 \u0440\u0430\u0437\u043c\u0435\u0440\u044b, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0441\u0442\u044f\u043d\u0443\u0442\u044c \u043e\u043a\u043d\u043e, \u0430 \u0432\u0442\u043e\u0440\u043e\u0435 \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439.<\/p>\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u0430 \u043d\u0435 \u043e\u043a\u043d, \u0442\u043e \u0432\u0441\u0435 \u043e\u043d\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043f\u043e\u0445\u043e\u0436\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c. \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 <code>width<\/code>&#8212;<code>height<\/code> \u0437\u0430\u0434\u0430\u044e\u0442 \u0436\u0451\u0441\u0442\u043a\u0438\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u044b, \u0434\u0435\u043b\u0430\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043d\u0435\u043e\u0442\u0437\u044b\u0432\u0447\u0438\u0432\u044b\u043c\u0438, \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438. <code>min-<\/code>, <code>max-<\/code> \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0437\u0430\u0434\u0430\u044e\u0442 \u0433\u0440\u0430\u043d\u0438\u0446\u044b, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0441\u0442\u044f\u0433\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u0430 \u0432\u043e\u0442 <code>preferred-<\/code> \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0437\u0430\u0434\u0430\u0451\u0442 \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u044b, \u043d\u043e \u043d\u0435 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442, \u0447\u0442\u043e \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442. \u0422\u043e \u0435\u0441\u0442\u044c, \u0443\u0441\u043b\u043e\u0432\u043d\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0443 \u0437\u0430\u0434\u0430\u043b\u0438 <code>preferred-width: 10000px<\/code>, \u0430 \u0448\u0438\u0440\u0438\u043d\u0430 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f \u0432\u0441\u0435\u0433\u043e <code>200px<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d \u0432 \u044d\u0442\u0438 \u043f\u0440\u0435\u0434\u0435\u043b\u044b.<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b1f\/8f4\/d80\/b1f8f4d8035b5a42cb69bef3eaa797cd.gif\" alt=\"\u041f\u0430\u0441\u043a\u0430\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u0433\u043e\u0440\u0434\u0438\u0442\u044c\u0441\u044f \u043d\u0430\u043c\u0438\" title=\"\u041f\u0430\u0441\u043a\u0430\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u0433\u043e\u0440\u0434\u0438\u0442\u044c\u0441\u044f \u043d\u0430\u043c\u0438\" width=\"300\" height=\"500\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b1f\/8f4\/d80\/b1f8f4d8035b5a42cb69bef3eaa797cd.gif\"\/><\/p>\n<div><figcaption>\u041f\u0430\u0441\u043a\u0430\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u0433\u043e\u0440\u0434\u0438\u0442\u044c\u0441\u044f \u043d\u0430\u043c\u0438<\/figcaption><\/div>\n<\/figure>\n<h2>\u0412\u0435\u0437\u0434\u0435\u0441\u0443\u0449\u0438\u0439 \u0432\u0435\u0431<\/h2>\n<p>\u042f \u043a\u0430\u043a-\u0442\u043e \u0434\u0430\u0436\u0435 \u0438 \u043d\u0435 \u0437\u0430\u0434\u0443\u043c\u044b\u0432\u0430\u043b\u0441\u044f \u043e \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440 \u0432 \u0432\u0435\u0431, \u043d\u043e <a class=\"mention\" href=\"\/users\/stanukih\">@stanukih<\/a> \u0437\u0430\u0434\u0430\u043b \u043d\u0430 \u044d\u0442\u043e\u0442 \u0441\u0447\u0451\u0442 \u0432\u043e\u043f\u0440\u043e\u0441, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u043e\u0448\u0443 \u0432\u0430\u0448\u0435\u043c\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044e&#8230; *\u0431\u0430\u0440\u0430\u0431\u0430\u043d\u043d\u0430\u044f \u0434\u0440\u043e\u0431\u044c*&#8230; \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435!<\/p>\n<p>\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u043e \u043a\u043e\u0434\u0443 \u0431\u0443\u0434\u0443\u0442 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c\u0438, \u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0442\u0440\u043e\u0433\u0430\u0442\u044c \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u0442\u043e, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0438\u043b \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0438\u0442\u044c \u043a \u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0432 \u0432\u0435\u0431. \u0412\u0435\u0441\u044c \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 <a href=\"https:\/\/gitverse.ru\/ertanic\/calc-rs\/content\/calculator-web\" rel=\"noopener noreferrer nofollow\">\u0432\u0435\u0442\u043a\u0435<\/a>.<\/p>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 \u0432 \u043f\u0440\u0438\u0433\u043e\u0434\u043d\u044b\u0439 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0432\u0435\u0431\u0435 \u0432\u0438\u0434, \u043d\u0443\u0436\u0435\u043d \u0442\u0443\u043b\u0447\u0435\u0439\u043d <a href=\"https:\/\/rustwasm.github.io\/wasm-pack\/installer\/\" rel=\"noopener noreferrer nofollow\">wasm-pack<\/a>. \u041d\u043e \u0443 \u043d\u0430\u0441 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448 \u043a\u043e\u0434 \u0432 <a href=\"https:\/\/webassembly.org\/\" rel=\"noopener noreferrer nofollow\">WASM<\/a>&#8212;<u>\u043c\u043e\u0434\u0443\u043b\u044c<\/u>, \u0442\u0430\u043a \u043a\u0430\u043a \u0442\u0438\u043f \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 <code>bin<\/code>. \u0418\u0434\u0451\u043c \u0432 \u0444\u0430\u0439\u043b <code>Cargo.toml<\/code> \u0438 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u043c \u0435\u0433\u043e \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0432\u0438\u0434:<\/p>\n<pre><code class=\"rust\">[package] name = \"calc-rs\" version = \"0.1.0\" edition = \"2021\"  [lib] path = \"src\/main.rs\" # \u041c\u043e\u0436\u043d\u043e \u043d\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b src\/main.rs \u0432 src\/lib.rs crate-type = [\"cdylib\"]  [target.'cfg(target_arch = \"wasm32\")'.dependencies] wasm-bindgen = { version = \"0.2\" } web-sys = { version = \"0.3\", features=[\"console\"] }  [dependencies] slint = \"1.5.1\"  [build-dependencies] slint-build = \"1.5.1\"<\/code><\/pre>\n<p>\u041f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e. \u0422\u0435\u043f\u0435\u0440\u044c \u0448\u0430\u0433\u0430\u0435\u043c \u0432 \u043d\u0430\u0448 <code>src\/main.rs<\/code>, \u043e\u0442\u0440\u0435\u043a\u0430\u0435\u043c\u0441\u044f \u043e\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u043f\u043e\u0434\u0430\u0432\u043b\u044f\u0435\u043c \u0436\u0430\u043b\u043e\u0431\u044b \u043b\u0438\u043d\u0442\u0435\u0440\u0430, \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043f\u0440\u0435\u043b\u044e\u0434\u0438\u044e <code>wasm_bindgen<\/code> \u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0435\u043c\u0443 \u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430.<\/p>\n<pre><code class=\"rust\">#![no_std] #![warn(dead_code)]  #[cfg(target_arch = \"wasm32\")] use wasm_bindgen::prelude::*;  use slint::SharedString;  slint::include_modules!();  #[cfg_attr(target_arch = \"wasm32\", wasm_bindgen(start))] fn main() {     let app = AppWindow::new().unwrap();     app.set_window_title(SharedString::from(\"Calculator\"));     app.run().unwrap(); }<\/code><\/pre>\n<p>\u041f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0440\u0430\u043d\u0435\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u0441\u0431\u043e\u0440\u0449\u0438\u043a:<\/p>\n<pre><code class=\"powershell\">wasm-pack build --release --target web --no-default-features<\/code><\/pre>\n<p>\u042d\u0442\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u043e\u043c \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442 \u043d\u0430\u0448 Rust-\u043a\u043e\u0434 \u0432 WASM-\u043c\u043e\u0434\u0443\u043b\u044c \u0438 \u043a\u043e \u0432\u0441\u0435\u043c\u0443 \u044d\u0442\u043e\u043c\u0443 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0437\u0430 \u043d\u0430\u0441 JS-\u043e\u0431\u0451\u0440\u0442\u043a\u0443 \u0438 \u0444\u0430\u0439\u043b \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0442\u0438\u043f\u043e\u0432 Typescript. \u0420\u0430\u0437\u0432\u0435 \u043d\u0435 \u0441\u043a\u0430\u0437\u043a\u0430?<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/36e\/417\/39b\/36e41739b93fd37f74e7346e619d5622.png\" alt=\"\u0410\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u043f\u043e\u0441\u043b\u0435 wasm-pack\" title=\"\u0410\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u043f\u043e\u0441\u043b\u0435 wasm-pack\" width=\"207\" height=\"221\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/36e\/417\/39b\/36e41739b93fd37f74e7346e619d5622.png\"\/><\/p>\n<div><figcaption>\u0410\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u043f\u043e\u0441\u043b\u0435 wasm-pack<\/figcaption><\/div>\n<\/figure>\n<p>\u0421\u043e\u0437\u0434\u0430\u0451\u043c <code>index.html<\/code> \u0441 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u044b\u043c. Slint \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043a\u0430\u0442\u044c <code>canvas<\/code> \u0441 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c&#8230; \u00abcanvas\u00bb.<\/p>\n<pre><code class=\"xml\">&lt;!doctype html> &lt;html lang=\"en-US\">   &lt;head>     &lt;meta charset=\"utf-8\" \/>     &lt;title>Calculator&lt;\/title>     &lt;style>         * {             margin: 0;             padding: 0;         }          html,         body {             height: 100%;             width: 100%;         }          body {             display: flex;             justify-content: center;             align-items: center;         }     &lt;\/style>   &lt;\/head>   &lt;div id=\"spinner\" style=\"position: relative;\">     &lt;div class=\"spinner\">Loading...&lt;\/div>   &lt;\/div>   &lt;canvas id=\"canvas\" unselectable=\"on\">&lt;\/canvas>   &lt;body>     &lt;script type=\"module\">         import init from \".\/pkg\/calc_rs.js\";         init().finally(() => {             document.getElementById(\"spinner\").remove();         });     &lt;\/script>   &lt;\/body> &lt;\/html><\/code><\/pre>\n<p>\u041c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e html-\u0444\u0430\u0439\u043b\u0438\u043a, \u043d\u043e \u0443 \u0432\u0430\u0441 \u0431\u0443\u0434\u0435\u0442, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0440\u0443\u0433\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u0435 CORS-\u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440. \u041b\u0438\u0447\u043d\u043e \u044f \u0431\u0443\u0434\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f <a href=\"https:\/\/docs.python.org\/3\/library\/http.server.html\" rel=\"noopener noreferrer nofollow\">http.serve<\/a>r \u0438\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u0442\u0443\u043b\u0447\u0435\u0439\u043d\u0430 Python.<\/p>\n<pre><code class=\"powershell\">python -m http.server<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ae0\/13c\/4c8\/ae013c4c88b1a9d6d0ab788ae07eec47.png\" alt=\"\u041c\u043e\u0436\u0435\u0442, \u041f\u0430\u0441\u043a\u0430\u043b\u044c \u0438 \u043f\u043e\u0445\u0432\u0430\u043b\u0438\u0442, \u0430 \u0432\u043e\u0442 \u041c\u0430\u0440\u043a \u0423\u0438\u043b\u043b\u0435\u0440 \u0434\u043e\u0441\u0442\u0430\u043b \u0442\u043e\u043f\u043e\u0440...\" title=\"\u041c\u043e\u0436\u0435\u0442, \u041f\u0430\u0441\u043a\u0430\u043b\u044c \u0438 \u043f\u043e\u0445\u0432\u0430\u043b\u0438\u0442, \u0430 \u0432\u043e\u0442 \u041c\u0430\u0440\u043a \u0423\u0438\u043b\u043b\u0435\u0440 \u0434\u043e\u0441\u0442\u0430\u043b \u0442\u043e\u043f\u043e\u0440...\" width=\"1301\" height=\"763\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ae0\/13c\/4c8\/ae013c4c88b1a9d6d0ab788ae07eec47.png\"\/><\/p>\n<div><figcaption>\u041c\u043e\u0436\u0435\u0442, \u041f\u0430\u0441\u043a\u0430\u043b\u044c \u0438 \u043f\u043e\u0445\u0432\u0430\u043b\u0438\u0442, \u0430 \u0432\u043e\u0442 \u041c\u0430\u0440\u043a \u0423\u0438\u043b\u043b\u0435\u0440 \u0434\u043e\u0441\u0442\u0430\u043b \u0442\u043e\u043f\u043e\u0440&#8230;<\/figcaption><\/div>\n<\/figure>\n<p>\u042f \u0442\u0430\u043a \u0438 \u043d\u0435 \u043f\u043e\u043d\u044f\u043b, \u043a\u0430\u043a \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0440\u0430\u0441\u0442\u044f\u0433\u0438\u0432\u0430\u0442\u044c\u0441\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u043e\u043c \u043a\u0430\u043d\u0432\u0430\u0441\u0443 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0442\u0435 \u0436\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u044b, \u0447\u0442\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u0432 width \u0438 height. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c, \u0435\u0441\u043b\u0438 \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u0430\u0445, \u044d\u0442\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0438 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u0432\u0438\u0436\u0443, \u0442\u0430\u043a \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0431\u0438\u043d\u0434\u044b \u043a JS, \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u043e\u043a\u043d\u0430 \u0438 \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432.<\/p>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043d\u0435 \u044f \u043e\u0434\u0438\u043d \u0437\u0430\u043c\u0435\u0442\u0438\u043b, \u0447\u0442\u043e \u0432\u0441\u044f \u0432\u0451\u0440\u0441\u0442\u043a\u0430 \u043f\u0435\u0440\u0435\u043d\u044f\u043b\u0430 \u043f\u044c\u044f\u043d\u044b\u0439 \u0441\u0442\u0438\u043b\u044c \u0441\u0442\u0430\u0440\u0438\u043a\u0430 \u0421\u043e\u0443? \u0421\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u044d\u0442\u043e \u0438\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0432\u043c\u0435\u0441\u0442\u043e <code>GridLayout<\/code> \u0431\u044b\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b <code>VerticalLayout<\/code> \u0438 <code>HorizontalLayout<\/code>, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0435\u0440\u0432\u044b\u0439 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0446\u0438\u043a\u043b\u044b.<\/p>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0446\u0432\u0435\u0442\u0430 \u0448\u0440\u0438\u0444\u0442\u0430 \u0438 \u043a\u043d\u043e\u043f\u043e\u043a \u2013 \u0441\u0430\u043c\u0430\u044f \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0430\u044f \u0442\u0430\u0439\u043d\u0430 \u0434\u043b\u044f \u043c\u0435\u043d\u044f. \u041b\u0438\u0431\u043e \u044d\u0442\u043e \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f WebGL, \u043b\u0438\u0431\u043e \u0442\u0435\u043c\u044b \u0438\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043d\u0435 \u043f\u043e\u0434\u0433\u0440\u0443\u0436\u0430\u044e\u0442\u0441\u044f \u043f\u043e \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c.<\/p>\n<p>\u041f\u0440\u043e \u0447\u0430\u0441\u0442\u044c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438, \u0433\u0434\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f \u0432 WASM \u0438 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430, \u044f \u0432\u043e\u043e\u0431\u0449\u0435 \u043c\u043e\u043b\u0447\u0443, \u0435\u0451, \u0441\u0447\u0438\u0442\u0430\u0439, \u0438 \u043d\u0435\u0442. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0441\u0447\u0438\u0442\u0430\u0442\u044c, \u0447\u0442\u043e Slint, \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u043f\u043e\u043a\u0430 \u0447\u0442\u043e \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043d\u0438\u0446. \u0411\u043e\u043b\u0435\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u0434\u043b\u044f \u0432\u0435\u0431\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c <a href=\"https:\/\/yew.rs\/\" rel=\"noopener noreferrer nofollow\">Yew<\/a> \u0438\u043b\u0438 \u0432\u043e\u043e\u0431\u0449\u0435 \u0444\u0443\u043b\u043b\u0441\u0442\u0435\u043a \u043a\u0440\u0435\u0439\u0442 <a href=\"https:\/\/dioxuslabs.com\/\" rel=\"noopener noreferrer nofollow\">Dioxus<\/a>.<\/p>\n<h2>\u0418\u0442\u043e\u0433\u043e<\/h2>\n<p>\u0411\u044b\u043b \u043f\u0440\u043e\u0439\u0434\u0435\u043d \u043f\u0443\u0442\u044c \u043e\u0442 \u0441\u0447\u0451\u0442\u0447\u0438\u043a\u0430 \u0434\u043e \u043a\u0440\u0438\u0432\u043e\u0433\u043e \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440\u0430, \u0432 \u0445\u043e\u0434\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u044b\u043b\u0438 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 Slint, \u0445\u043e\u0442\u044c \u0438 \u0432 \u0441\u0436\u0430\u0442\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435 (\u043f\u0440\u0438\u0432\u0435\u0442, \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u044b). \u041f\u043e\u0434 \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435 \u044f \u0438\u043c\u0435\u044e \u0432\u0432\u0438\u0434\u0443 \u0438 i18n, \u0438 \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0437\u0430\u043f\u0440\u043e\u0441 \u043a API \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0438\u043b\u0438 \u0432\u044b\u0437\u043e\u0432 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439.<\/p>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u043e\u043a\u0440\u043e\u0435\u0442, \u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u043e \u0438 \u043d\u0435\u0446\u0435\u043b\u0435\u0441\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u043e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u044f \u043d\u0435 \u0432\u0438\u0434\u0435\u043b \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e, \u0433\u0434\u0435 \u0431\u044b\u043b \u0431\u044b \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0440\u043d\u044b\u0439 drag`n`drop. \u0418 \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043d\u0435 \u043d\u0430\u0448\u0451\u043b \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u0441\u0442\u0438 \u043e\u043a\u043d\u0430, \u0434\u043e \u0447\u0435\u0433\u043e \u044f \u0434\u043e\u0448\u0451\u043b \u0441\u0430\u043c. \u0410 GridLayout \u0434\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u0441\u044b\u0440\u043e\u0439 \u0438 \u0432\u044b \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0446\u0438\u043a\u043b\u0430\u043c\u0438.<\/p>\n<p>\u041d\u043e \u0441\u0443\u0434\u044f \u043f\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0438\u0434\u0451\u0442 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c \u0445\u043e\u0434\u043e\u043c. \u0425\u043e\u0442\u044f \u0441\u0442\u043e\u0438\u0442 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c, \u0447\u0442\u043e \u043e\u043d\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 \u0441\u0432\u043e\u0439 DSL \u0438 \u0442\u0440\u0438 \u042f\u041f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u043d\u0430 \u0441\u0447\u0451\u0442 \u0446\u0435\u043b\u0435\u0441\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f DSL \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0442\u0440\u0451\u0445 \u042f\u041f, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e Node.js, \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0437\u0430\u043c\u0435\u0434\u043b\u044f\u0435\u0442 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (\u043e\u0431\u043e\u0436\u0430\u044e \u0442\u0430\u0432\u0442\u043e\u043b\u043e\u0433\u0438\u0438). \u041c\u043e\u0433\u043b\u0438 \u0431\u044b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c\u0441\u044f \u043b\u0438\u0431\u043e\u0439 \u043d\u0430 \u0442\u0435\u0445 \u0436\u0435 \u043f\u043b\u044e\u0441\u0430\u0445, \u0430 \u0443\u0436 \u0431\u0438\u043d\u0434\u044b \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e \u0441\u0430\u043c\u043e \u0431\u044b \u0441\u043c\u043e\u0433\u043b\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c.<\/p>\n<p>\u041d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0432\u0441\u0435\u0433\u043e \u0432\u044b\u0448\u0435\u0441\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u043c\u043e\u0433\u0443 \u043f\u043e\u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0440\u0443\u0433\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443, \u0435\u0441\u043b\u0438 \u0432\u0430\u0448\u0430 \u0446\u0435\u043b\u044c \u043d\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043f\u0440\u0438\u043d\u0442\u0435\u0440\u0430 \u0438\u043b\u0438 \u043a\u043e\u0444\u0435\u043c\u0430\u0448\u0438\u043d\u044b, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Tauri, Avalonia \u0438\u043b\u0438 Flutter.<\/p>\n<h2>\u0421\u0441\u044b\u043b\u043e\u0447\u043a\u0438<\/h2>\n<p>\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441 \u043a\u043e\u0434\u043e\u043c: <a href=\"https:\/\/gitverse.ru\/ertanic\/calc-rs\" rel=\"noopener noreferrer nofollow\">https:\/\/gitverse.ru\/ertanic\/calc-rs<\/a>.<\/p>\n<p>\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 Slint: <a href=\"https:\/\/github.com\/slint-ui\/slint\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/slint-ui\/slint<\/a>.<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/804655\/\"> https:\/\/habr.com\/ru\/articles\/804655\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0417\u0430\u0447\u0435\u043c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440? \u0414\u0430 \u043d\u0435\u0437\u0430\u0447\u0435\u043c, \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u0430\u043a \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u043b\u044f \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u044f GUI-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438.<\/p>\n<p>\u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u044f \u0445\u043e\u0442\u0435\u043b \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u043a\u0440\u0435\u0439\u0442\u044b, \u043a\u0430\u043a GPUI, Floem \u0438 Xilem, \u043d\u043e \u043f\u0435\u0440\u0432\u0430\u044f, \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u043f\u043e\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0434 MacOS \u0438 Linux, \u0432\u0442\u043e\u0440\u0430\u044f \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u043a\u043e\u043d\u043a\u0443 \u043e\u043a\u043d\u0443 \u0438 \u043a\u0443\u0448\u0430\u0435\u0442 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u044b \u043f\u043e\u0431\u043e\u043b\u044c\u0448\u0435 Webview \u0432 Tauri, \u0430 \u0434\u043e \u0442\u0440\u0435\u0442\u044c\u0435\u0439 \u044f \u0442\u0430\u043a \u0438 \u043d\u0435 \u0434\u043e\u0431\u0440\u0430\u043b\u0441\u044f, \u0443\u0437\u043d\u0430\u0432 \u043e\u0431 Slint.<\/p>\n<p>\u041e\u0431 Slint \u0435\u0441\u0442\u044c \u0432\u0441\u0435\u0433\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u043e\u0441\u0442\u043d\u044b\u0445 \u043f\u043e\u0441\u0442\u043e\u0432 \u043d\u0430 \u0425\u0430\u0431\u0440\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u0447\u0442\u043e \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0435.<\/p>\n<h2>\u041e\u0431 Slint<\/h2>\n<p>Slint &#8212; \u044d\u0442\u043e GUI-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u043f\u043e \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u0438\u044f\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0432\u043e\u0435\u0439 \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u043e\u0441\u0442\u044c\u044e \u0438 \u043b\u0435\u0433\u043a\u043e\u0441\u0442\u044c\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f. \u0421\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u044f\u0441\u044c \u0441 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u0430\u043c\u0438, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 Slint \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u044e\u0442, \u0447\u0442\u043e \u0438\u0445 \u0440\u0430\u043d\u0442\u0430\u0439\u043c \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0432\u0441\u0435\u0433\u043e 300 \u043a\u0431 \u0432 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0435\u0433\u043e \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u044b\u043c \u0432\u044b\u0431\u043e\u0440\u043e\u043c \u0434\u043b\u044f embedded-\u0441\u0438\u0441\u0442\u0435\u043c.<\/p>\n<p>\u0424\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 Rust, C++ \u0438 Node.js, \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 DSL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0442\u0435\u043c \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432 \u0438 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b. DSL \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0437 \u0441\u0435\u0431\u044f \u043d\u0435\u043a\u0443\u044e \u0441\u043c\u0435\u0441\u044c CSS \u0438 SwiftUI, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0438\u0436\u0435.<\/p>\n<p>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 <a href=\"https:\/\/slint.dev\/get-started#integrate-with-ides\" rel=\"noopener noreferrer nofollow\">\u043f\u043b\u0430\u0433\u0438\u043d\u044b<\/a> \u0434\u043b\u044f \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0438 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c IDE \u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u043e\u0432 \u043a\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0430\u0451\u0442 \u043d\u0430\u043c \u0449\u0435\u043f\u043e\u0442\u043a\u0443 intellisense \u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043a\u0440\u0438\u0432\u043e\u0439 \u043f\u0440\u0435\u0432\u044c\u044e, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 <code>default-font-*<\/code>. \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043a \u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043a\u0430\u0442\u0438\u0442\u044c \u0435\u0449\u0451 <a href=\"https:\/\/codeium.com\/\" rel=\"noopener noreferrer nofollow\">Codeium<\/a>, \u0443 \u043d\u0438\u0445 \u0435\u0441\u0442\u044c \u0431\u0435\u0442\u0430-\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 Slint DSL (\u0445\u043e\u0442\u044f \u043d\u0430 \u0447\u0443\u0434\u043e \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e).<\/p>\n<p>Slint \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u044f\u043c\u0438.<\/p>\n<figure class=\"full-width\"><\/figure>\n<h2>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u0440\u043e\u0435\u043a\u0442<\/h2>\n<p>\u0414\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u043c\u0430\u043b\u043e \u0437\u043d\u0430\u043a\u043e\u043c \u0441 Rust, \u0431\u0443\u0434\u0443 \u0432\u0441\u0451 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c (\u043d\u0443, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c-\u0442\u043e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u044f\u0437\u044b\u043a\u0430, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0438 \u0431\u0435\u0437 \u043c\u0435\u043d\u044f \u0441\u043c\u043e\u0436\u0435\u0442\u0435, \u0434\u0430? \u0414\u0430, \u0432\u0435\u0434\u044c?&#8230;). \u041f\u043e\u044d\u0442\u043e\u043c\u0443&#8230; \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u0440\u043e\u0435\u043a\u0442! \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u043c\u0438:<\/p>\n<pre><code class=\"powershell\">cargo new # \u0438\u043b\u0438 cargo init<\/code><\/pre>\n<p>\u041f\u043e \u0441\u0443\u0442\u0438, \u043e\u0431\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u0435\u043b\u0430\u044e\u0442 \u043e\u0434\u043d\u043e \u0438 \u0442\u043e \u0436\u0435, \u043d\u043e \u0434\u043b\u044f <code>cargo new<\/code> \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043c\u044f \u043d\u043e\u0432\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438. \u041d\u043e \u0435\u0441\u043b\u0438 \u0434\u043b\u044f <code>cargo init<\/code> \u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435, \u043e\u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u043f\u0440\u043e\u0435\u043a\u0442 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438.<\/p>\n<blockquote>\n<p>\u0415\u0441\u043b\u0438 \u0412\u0430\u043c \u043d\u0435\u00a0\u043d\u0443\u0436\u0435\u043d \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043f\u0440\u0438\u00a0\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0441\u0442\u043e\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u043b\u0430\u0433 <code>--vcs none<\/code>.<\/p>\n<\/blockquote>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0435\u043a\u0442 \u0431\u0443\u0434\u0435\u0442 \u043d\u043e\u0441\u0438\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 <code>calc-rs<\/code>. \u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0432\u0448\u0438\u0441\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442 \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439:<\/p>\n<figure class=\"\">\n<div><figcaption>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<h2>\u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h2>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d <code>cargo-edit<\/code>. \u041f\u043b\u0430\u0433\u0438\u043d \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439:<\/p>\n<pre><code class=\"powershell\">cargo install cargo-edit<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"powershell\">cargo add slint                                            # GUI cargo add --build slint-build                              # \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 DSL<\/code><\/pre>\n<h2>Slint, \u0438\u043b\u0438 \u043f\u0440\u0430\u0432\u043e\u0441\u043b\u0430\u0432\u043d\u044b\u0439 GUI<\/h2>\n<p>Slint \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 DSL. \u0415\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043c\u0430\u043a\u0440\u043e\u0441 <code>slint::slint!<\/code>. \u0418 \u044d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0443\u0434\u043e\u0431\u043d\u043e, \u0432\u0435\u0434\u044c \u043c\u043e\u0436\u043d\u043e \u0432 \u043e\u0434\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0438 \u043b\u043e\u0433\u0438\u043a\u0443, \u0438 \u0441\u0442\u0438\u043b\u0438. \u041e\u0434\u043d\u0430\u043a\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0439 \u0441 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0444\u0430\u0439\u043b\u0430\u043c\u0438.<\/p>\n<blockquote>\n<p>A\u00a0<strong>domain-specific language<\/strong>\u00a0(<strong>DSL<\/strong>) is a\u00a0computer language\u00a0specialized to a particular application\u00a0domain. This is in contrast to a\u00a0general-purpose language\u00a0(GPL), which is broadly applicable across domains. <\/p>\n<p>\u0418\u043b\u0438 \u043f\u043e \u043d\u0430\u0448\u0435\u043d\u0441\u043a\u0438:<\/p>\n<p>\u041f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u044f\u0437\u044b\u043a (DSL) &#8212; \u044d\u0442\u043e \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043d\u044b\u0439 \u044f\u0437\u044b\u043a, \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043f\u0440\u0438\u043a\u043b\u0430\u0434\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u044f\u0437\u044b\u043a\u0430 \u043e\u0431\u0449\u0435\u0433\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f (GPL), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0448\u0438\u0440\u043e\u043a\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u043e\u0431\u043b\u0430\u0441\u0442\u044f\u0445.<\/p>\n<p>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a: <a href=\"https:\/\/en.wikipedia.org\/wiki\/Domain-specific_language\" rel=\"noopener noreferrer nofollow\">wikipedia.org<\/a>. \u0421\u0442\u0430\u0442\u044c\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0438\u0441\u0447\u0435\u0440\u043f\u044b\u0432\u0430\u044e\u0449\u0430\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435 \u043d\u0430\u0434\u043e \u0432 \u043c\u0435\u043d\u044f \u0442\u0430\u043f\u043a\u0430\u043c\u0438 \u043a\u0438\u0434\u0430\u0442\u044c \u0437\u0430 \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0432\u0438\u043a\u0438.<\/p>\n<\/blockquote>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0430\u043f\u043a\u0443 <code>components<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b <code>app.slint<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u0447\u0451\u0442\u0447\u0438\u043a.<\/p>\n<pre><code class=\"rust\">import { VerticalBox, HorizontalBox, Button } from \"std-widgets.slint\"; export component AppWindow inherits Window {     in property &lt;string> window_title;      width: 400px;     height: 500px;     title: window_title;     default-font-size: 20px;      property &lt;int> count: 0;      VerticalBox {         alignment: center;              Text {             font-size: 30px;             horizontal-alignment: center;             text: \"Count: \" + count;         }         HorizontalBox {             Button {                 text: \"add\";                 clicked => {                     root.count += 1;                 }             }             Button {                 text: \"subtract\";                 clicked => {                     if root.count != 0 {                         root.count -= 1;                     }                 }             }         }     } }<\/code><\/pre>\n<blockquote>\n<p>\u0414\u043b\u044f \u0432\u0451\u0440\u0441\u0442\u043a\u0438 \u0435\u0441\u0442\u044c \u0442\u0430\u043a\u0438\u0435 layout, \u043a\u0430\u043a <code>VerticalLayout<\/code>, <code>HorizontalLayout<\/code> \u0438 <code>GridLayout<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0430. \u0418 \u0432\u044b \u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f <code>VerticalBox<\/code> \u0438 <code>HorizontalBox<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0438\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432. \u0412\u0441\u044f \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043f\u0440\u0435\u0434\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b \u043e\u0442\u0441\u0442\u0443\u043f\u044b \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u043e\u043c \u043f\u043e \u0442\u0438\u043f\u0443 \u0442\u0435\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0431-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e <a href=\"https:\/\/code.mu\/ru\/markup\/book\/supreme\/cross-browser-compatibility\/reset\/\" rel=\"noopener noreferrer nofollow\">\u043e\u0431\u043d\u0443\u043b\u044f\u044e\u0442<\/a>.  <\/p>\n<\/blockquote>\n<p>\u0412 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0444\u0430\u0439\u043b <code>build.rs<\/code>, \u044f\u0432\u043b\u044f\u044e\u0449\u0438\u0439\u0441\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u043c \u0441\u0431\u043e\u0440\u043a\u0438, \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043d\u0435\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>main<\/code> \u0441 \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>compile<\/code>. \u0422\u0435\u043f\u0435\u0440\u044c <code>app.slint<\/code> \u2013 \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430, \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c. \u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442 DSL \u0432 \u043a\u043e\u0434 Rust. \u0422\u043e \u0435\u0441\u0442\u044c \u0440\u0430\u043d\u0435\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 AppWindow \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d \u0432 <code>struct AppWindow<\/code>.<\/p>\n<pre><code class=\"rust\">fn main() {     slint_build::compile(\"components\/app.slint\").unwrap(); }<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043c\u0430\u043a\u0440\u043e\u0441 <code>slint::include_modules!()<\/code> \u0432 \u0444\u0430\u0439\u043b\u0435 <code>src\/main.rs<\/code> \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u0435\u043c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043d\u0430\u0448\u0435\u0433\u043e <code>AppWindow<\/code>.<\/p>\n<pre><code class=\"rust\">use slint::SharedString;  slint::include_modules!();  fn main() -> Result&lt;(), Box&lt;dyn std::error::Error>> {     let app = AppWindow::new()?;     app.set_window_title(SharedString::from(\"Counter\"));     app.run()?;      Ok(()) }<\/code><\/pre>\n<p>\u041c\u0435\u0442\u043e\u0434 <code>set_window_title<\/code> \u0431\u044b\u043b \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u0438\u0437 <code>in property window_title<\/code>, \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0432 \u0444\u0430\u0439\u043b\u0435 <code>components\/app.slint<\/code>. \u0421\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 <code>in<\/code> \u0434\u0435\u043b\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>windows_title<\/code>, \u0438 \u0435\u0441\u043b\u0438 \u0435\u0433\u043e \u0443\u0431\u0440\u0430\u0442\u044c, \u0442\u043e \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0441\u0447\u0438\u0442\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u043c \u0438 \u043c\u0435\u0442\u043e\u0434 <code>set_window_title<\/code>, \u043a\u0430\u043a \u0438 \u043c\u0435\u0442\u043e\u0434 <code>get_window_title<\/code>, \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d. \u0412\u044b\u0434\u0435\u0440\u0436\u043a\u0430 \u0438\u0437 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043d\u0430 \u0441\u0447\u0451\u0442 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u0430:<\/p>\n<blockquote>\n<p>\u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u043a \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a \u044d\u0442\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043e \u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u0444\u0430\u0439\u043b:<\/p>\n<p><strong>private<\/strong> (\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e): \u0414\u043e\u0441\u0442\u0443\u043f \u043a \u044d\u0442\u043e\u043c\u0443 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0443 \u0432\u043e\u0437\u043c\u043e\u0436\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0437 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<p><strong>in<\/strong>: \u0421\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0445\u043e\u0434\u043d\u044b\u043c. \u041e\u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0440\u0438\u0432\u044f\u0437\u043e\u043a \u0438\u043b\u0438 \u043f\u0443\u0442\u0435\u043c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043e\u0431\u0440\u0430\u0442\u043d\u044b\u0445 \u0432\u044b\u0437\u043e\u0432\u0430\u0445. \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u043d\u043e \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0435\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<p><strong>out<\/strong>: \u0412\u044b\u0445\u043e\u0434\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c. \u041e\u043d\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432.<\/p>\n<p><strong>in-out<\/strong>: \u042d\u0442\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043e \u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043e \u043a\u0435\u043c \u0443\u0433\u043e\u0434\u043d\u043e.<\/p>\n<p>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a: <a href=\"https:\/\/releases.slint.dev\/1.5.1\/docs\/slint\/src\/language\/syntax\/properties#properties\" rel=\"noopener noreferrer nofollow\">slint.dev<\/a>.<\/p>\n<p>\u041d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u043f\u043e\u043d\u044f\u043b \u0441\u043c\u044b\u0441\u043b \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430 <strong>in-out<\/strong>, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c <strong>in<\/strong>, \u0434\u0435\u043b\u0430\u044e\u0449\u0438\u0439 \u0440\u043e\u0432\u043d\u043e \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0ca0_\u0cb0\u0cc3. \u041f\u0440\u043e\u0448\u0443 \u0437\u043d\u0430\u044e\u0449\u0438\u0445 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u043e\u0431 \u044d\u0442\u043e\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435.<\/p>\n<\/blockquote>\n<p><code>cargo run<\/code> \u2013 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043d\u0430\u0448 \u0441\u0447\u0451\u0442\u0447\u0438\u043a-\u043d\u0435\u0434\u043e\u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440:<\/p>\n<figure class=\"\">\n<div><figcaption>&#171;Wake the F*** up,\u00a0Samurai<em>.<\/em>\u00a0We have a city to burn.&#187;<\/figcaption><\/div>\n<\/figure>\n<blockquote>\n<p>\u0417\u0430\u0431\u0430\u0432\u043d\u043e \u0442\u043e, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u043d\u0430\u0436\u0430\u043b\u0438 Tab, \u0442\u043e \u0432\u0440\u044f\u0434 \u043b\u0438 \u0443\u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0441\u043d\u044f\u0442\u044c \u0444\u043e\u043a\u0443\u0441 \u0441 \u043a\u043d\u043e\u043f\u043e\u043a \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f (\u3186_\u3186).<\/p>\n<\/blockquote>\n<h2>\u041c\u0443\u043b\u044c\u0442\u0438\u044f\u0437\u044b\u0447\u043d\u043e\u0441\u0442\u044c<\/h2>\n<p>Slint \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u043d\u0430\u0446\u0438\u043e\u043d\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <a href=\"https:\/\/www.gnu.org\/software\/gettext\/\" rel=\"noopener noreferrer nofollow\">Gettext<\/a> \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/releases.slint.dev\/1.5.1\/docs\/slint\/src\/language\/concepts\/translations\" rel=\"noopener noreferrer nofollow\">\u043c\u0430\u043a\u0440\u043e\u0441\u044b<\/a>, \u0447\u0442\u043e, \u043a\u0430\u043a \u043f\u043e-\u043c\u043d\u0435, \u0442\u0430\u043a\u043e\u0435 \u0441\u0435\u0431\u0435. \u041f\u043e\u0447\u0435\u043c\u0443? \u2013 \u044f \u0447\u0430\u0441\u0430 \u0442\u0440\u0438 \u043f\u044b\u0442\u0430\u043b\u0441\u044f \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u043d\u043e \u044f \u0442\u0430\u043a \u0438 \u043d\u0435 \u043f\u043e\u043d\u044f\u043b, \u043f\u043e\u0447\u0435\u043c\u0443 \u043d\u0438 \u044d\u0442\u043e\u0442 \u043c\u043e\u0434\u0443\u043b\u044c, \u043d\u0438 \u043c\u043e\u0434\u0443\u043b\u044c \u043b\u043e\u0433\u043e\u0432 Slint \u0442\u0430\u043a \u0438 \u043d\u0435 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438, \u0430 \u0432 \u0434\u043e\u043a\u0430\u0445 \u0447\u0443\u0442\u044c \u043b\u0438 \u043d\u0435 \u043f\u0430\u0440\u0443 \u0441\u043b\u043e\u0432 \u043e \u043d\u0438\u0445 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e (\u256f\u00b0\u25a1\u00b0\uff09\u256f\ufe35 \u253b\u2501\u253b. \u0415\u0441\u043b\u0438 \u043a\u043e\u043c\u0443 \u0431\u0443\u0434\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u0441\u043e\u0445\u0440\u0430\u043d\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u0441 gettext \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 <a href=\"https:\/\/gitverse.ru\/ertanic\/calc-rs\/content\/counter-gettext\" rel=\"noopener noreferrer nofollow\">\u0432\u0435\u0442\u043a\u0435<\/a> \u0440\u0435\u043f\u044b.<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/projectfluent.org\/\" rel=\"noopener noreferrer nofollow\">Fluent<\/a> \u043e\u0442 Mozilla (\u25cf&#8217;\u25e1&#8217;\u25cf). Fluent \u2013 \u0434\u0440\u0443\u0433\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0443\u0441\u0442\u0440\u0430\u043d\u044f\u044e\u0449\u0430\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441\u0432\u043e\u0435\u0433\u043e \u043f\u0440\u0435\u0434\u0448\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u0438\u043a\u0430 gettext. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0437 \u044d\u0442\u0438\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c:<\/p>\n<ol>\n<li>\n<p><strong>\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f.<\/strong>\u00a0\u0412 gettext \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u0445\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 (\u043e\u0431\u044b\u0447\u043d\u043e \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c) \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430. \u042d\u0442\u043e \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u0432\u044b\u043d\u0443\u0436\u0434\u0430\u044f \u0438\u0445 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u044d\u0442\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u043e\u0432.<\/p>\n<\/li>\n<\/ol>\n<ol start=\"2\">\n<li>\n<p><strong>\u0412\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439.<\/strong>\u00a0Gettext \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043d\u0430\u0431\u043e\u0440 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u043d\u0430\u0446\u0438\u043e\u043d\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438 \u2014 \u0434\u043b\u044f \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0447\u0438\u0441\u0435\u043b. Fluent \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044e \u0432\u0430\u0440\u0438\u0430\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u0441\u0442\u0440\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441 \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u0430\u043c\u0438.<\/p>\n<\/li>\n<\/ol>\n<ol start=\"3\">\n<li>\n<p><strong>\u0412\u043d\u0435\u0448\u043d\u0438\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b.<\/strong>\u00a0Gettext \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b, \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f \u0437\u0430\u0434\u0430\u0442\u044c \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u2014 \u0447\u0438\u0441\u0435\u043b, \u0434\u0430\u0442. Fluent \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u0430\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0442\u043e\u0447\u043d\u044b\u0435 \u0442\u0435\u043a\u0441\u0442\u044b \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432.<\/p>\n<\/li>\n<\/ol>\n<ol start=\"4\">\n<li>\n<p><strong>\u0410\u043d\u043d\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430.<\/strong>\u00a0Gettext \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0432\u0441\u0435 \u0442\u0440\u0438 \u0443\u0440\u043e\u0432\u043d\u044f \u0432 \u043e\u0434\u043d\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u043d\u0435\u0447\u0451\u0442\u043a\u043e\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435 (fuzzy). \u0412\u043e Fluent \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0434\u0432\u0430 \u0438\u0437 \u044d\u0442\u0438\u0445 \u0443\u0440\u043e\u0432\u043d\u0435\u0439 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043e\u0442 \u0442\u0440\u0435\u0442\u044c\u0435\u0433\u043e.<\/p>\n<\/li>\n<\/ol>\n<ol start=\"5\">\n<li>\n<p><strong>\u0424\u043e\u0440\u043c\u0430\u0442 \u0434\u0430\u043d\u043d\u044b\u0445.<\/strong>\u00a0Gettext \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0442\u0440\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 \u2014 *.po, *.pot \u0438 *.mo. Fluent \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0435\u0434\u0438\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0444\u0430\u0439\u043b\u0430 *.ftl, \u0447\u0442\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 \u0438 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0448\u0430\u0433\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u0440\u0430\u0441\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044e \u0432 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a: <a href=\"https:\/\/github.com\/projectfluent\/fluent\/wiki\/Fluent-vs-gettext\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 Fluent Project<\/a>.<\/p>\n<\/li>\n<\/ol>\n<blockquote>\n<p>\u041c\u0435\u043c \u043e\u0442\u0442\u0443\u0434\u0430 \u0436\u0435:<\/p>\n<p>Gettext \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 UTF-8. \u0412 \u0446\u0435\u043b\u043e\u043c, \u043d\u0430 \u044d\u0442\u043e\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 Unicode \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f.  <\/p>\n<\/blockquote>\n<p>\u0425\u043e\u0442\u044f Fluent \u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u0440\u0443\u0447\u0435 \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u043e\u0432 (\u0441\u043e\u0437\u0434\u0430\u043b \u043d\u0443\u0436\u043d\u044b\u0439 \u0444\u0430\u0439\u043b\u0438\u043a \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0448\u044c, \u0431\u0435\u0437 \u043d\u0430\u0434\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u0432 \u0440\u0430\u0437\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c), \u043d\u043e \u0432\u043e\u0442 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u0440\u0435\u0439\u0442\u044b \u043e\u0442 Fluent Project \u2013 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u044b\u0440\u0430\u044f \u0448\u043b\u044f\u043f\u0430. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043a\u043e\u0441\u0442\u044b\u043b\u0438 \u0431\u0435\u0437 \u0438\u0437\u043b\u0438\u0448\u0435\u0441\u0442\u0432 (\u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u044c, \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043b\u043e\u043a\u0430\u043b\u0435\u0439, \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a \u0438 \u0442.\u043f.).<\/p>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041d\u043e\u0432\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<pre><code class=\"powershell\">cargo add thiserror fluent sys-locale unic-langid cargo add --build copy_to_output<\/code><\/pre>\n<p><strong>src\/file.rs<\/strong>:<\/p>\n<pre><code class=\"rust\">use std::{env, path::{Path, PathBuf}};  use thiserror::Error;  #[derive(Error, Debug)] pub enum FileReadError {     #[error(\"Unable to read file: {0}\")]     ReadError(String, String),     #[error(\"Unable to read file as UTF-8\")]     Utf8Error }  \/\/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u043a \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 pub fn get_dir_path&lt;T: AsRef&lt;Path>>(subfolder: T) -> PathBuf {     let folder = subfolder.as_ref();     get_root_dir().join(folder) }  \/\/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u043a \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0439 \u0444\u0430\u0439\u043b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b pub fn get_root_dir() -> PathBuf {     env::current_exe()         .expect(\"Unable to get a exe path.\")  <\/code><\/pre>\n<\/div>\n<\/details>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-372484","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/372484","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=372484"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/372484\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=372484"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=372484"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=372484"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}