forked from eatvio/eatvio_app
feat: integrate MarkdownHtmlWidget for improved markdown rendering in blog and diet components
This commit is contained in:
67
lib/core/utils/markdown_utils.dart
Normal file
67
lib/core/utils/markdown_utils.dart
Normal file
@@ -0,0 +1,67 @@
|
||||
/// Утилиты для обработки markdown текста
|
||||
class MarkdownUtils {
|
||||
/// Обрабатывает markdown текст:
|
||||
/// - Исправляет неправильный синтаксис markdown ссылок
|
||||
/// - Автоматически преобразует URL в markdown ссылки
|
||||
/// - Преобразует **текст** в <b>текст</b> для надежного отображения жирного текста
|
||||
static String processMarkdown(String text) {
|
||||
// Сначала исправляем неправильный синтаксис markdown ссылок
|
||||
// Например: [http://example.com](url) -> [http://example.com](http://example.com)
|
||||
final wrongLinkRegex = RegExp(r'\[(https?://[^\]]+|www\.[^\]]+)\]\(([^\)]+)\)');
|
||||
text = text.replaceAllMapped(wrongLinkRegex, (match) {
|
||||
final urlInText = match.group(1)!;
|
||||
if (!urlInText.startsWith('http://') && !urlInText.startsWith('https://') && !urlInText.startsWith('www.')) {
|
||||
return match.group(0)!;
|
||||
}
|
||||
final fullUrl = urlInText.startsWith('www.') ? 'https://$urlInText' : urlInText;
|
||||
return '[$urlInText]($fullUrl)';
|
||||
});
|
||||
|
||||
// Находим все существующие markdown ссылки и их позиции
|
||||
final linkRegex = RegExp(r'\[([^\]]+)\]\(([^\)]+)\)');
|
||||
final existingLinks = <_LinkRange>[];
|
||||
for (final linkMatch in linkRegex.allMatches(text)) {
|
||||
existingLinks.add(_LinkRange(linkMatch.start, linkMatch.end));
|
||||
}
|
||||
|
||||
// Регулярное выражение для поиска URL (http://, https://, www.)
|
||||
final urlRegex = RegExp(r'(https?://[^\s\)]+|www\.[^\s\)]+)', caseSensitive: false);
|
||||
|
||||
// Заменяем URL на markdown ссылки, если они еще не являются ссылками
|
||||
String result = text;
|
||||
int offset = 0;
|
||||
for (final urlMatch in urlRegex.allMatches(text)) {
|
||||
// Проверяем, не находится ли URL внутри существующей markdown ссылки
|
||||
bool isInsideLink = existingLinks.any((link) =>
|
||||
urlMatch.start >= link.start && urlMatch.end <= link.end);
|
||||
if (!isInsideLink) {
|
||||
final url = urlMatch.group(0)!;
|
||||
final fullUrl = url.startsWith('www.') ? 'https://$url' : url;
|
||||
final replacement = '[$url]($fullUrl)';
|
||||
result = result.replaceRange(
|
||||
urlMatch.start + offset,
|
||||
urlMatch.end + offset,
|
||||
replacement,
|
||||
);
|
||||
offset += replacement.length - url.length;
|
||||
}
|
||||
}
|
||||
|
||||
// Гарантируем, что жирный текст будет распознан
|
||||
// Заменяем **текст** на <b>текст</b> вручную для надежности
|
||||
final boldRegex = RegExp(r'\*\*([^*]+)\*\*');
|
||||
result = result.replaceAllMapped(boldRegex, (match) {
|
||||
return '<b>${match.group(1)}</b>';
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// Вспомогательный класс для хранения диапазона позиций ссылки
|
||||
class _LinkRange {
|
||||
final int start;
|
||||
final int end;
|
||||
|
||||
_LinkRange(this.start, this.end);
|
||||
}
|
||||
124
lib/core/widgets/markdown_html_widget.dart
Normal file
124
lib/core/widgets/markdown_html_widget.dart
Normal file
@@ -0,0 +1,124 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
import 'package:markdown/markdown.dart' as md;
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:eatvio_app/core/utils/markdown_utils.dart';
|
||||
|
||||
/// Переиспользуемый виджет для отображения HTML из markdown текста
|
||||
class MarkdownHtmlWidget extends StatelessWidget {
|
||||
/// Markdown текст для отображения
|
||||
final String markdownText;
|
||||
|
||||
/// Ширина изображений (по умолчанию ширина экрана минус 32)
|
||||
final double? imageWidth;
|
||||
|
||||
/// Цвет текста для body и параграфов
|
||||
final Color? textColor;
|
||||
|
||||
/// Размер шрифта (по умолчанию 16)
|
||||
final double? fontSize;
|
||||
|
||||
/// Callback для обработки нажатий на ссылки
|
||||
final OnTap? onLinkTap;
|
||||
|
||||
const MarkdownHtmlWidget({
|
||||
super.key,
|
||||
required this.markdownText,
|
||||
this.imageWidth,
|
||||
this.textColor,
|
||||
this.fontSize,
|
||||
this.onLinkTap,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Обрабатываем markdown текст
|
||||
final processedText = MarkdownUtils.processMarkdown(markdownText);
|
||||
|
||||
// Конвертируем markdown в HTML
|
||||
final htmlData = md.markdownToHtml(
|
||||
processedText,
|
||||
extensionSet: md.ExtensionSet.gitHubFlavored,
|
||||
);
|
||||
|
||||
final screenWidth = MediaQuery.of(context).size.width;
|
||||
final defaultImageWidth = imageWidth ?? (screenWidth - 32);
|
||||
final defaultTextColor = textColor ?? Colors.black87;
|
||||
final defaultFontSize = fontSize ?? 16.0;
|
||||
|
||||
return Html(
|
||||
data: htmlData,
|
||||
style: {
|
||||
"body": Style(
|
||||
margin: Margins.zero,
|
||||
padding: HtmlPaddings.zero,
|
||||
fontSize: FontSize(defaultFontSize),
|
||||
lineHeight: const LineHeight(1.5),
|
||||
color: defaultTextColor,
|
||||
),
|
||||
"p": Style(
|
||||
margin: Margins.only(bottom: 12),
|
||||
color: defaultTextColor,
|
||||
),
|
||||
"b, strong": Style(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black,
|
||||
),
|
||||
"h1, h2, h3, h4, h5, h6": Style(
|
||||
margin: Margins.only(top: 16, bottom: 8),
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
"h1": Style(fontSize: FontSize(24)),
|
||||
"h2": Style(fontSize: FontSize(20)),
|
||||
"h3": Style(fontSize: FontSize(18)),
|
||||
"ul, ol": Style(
|
||||
margin: Margins.only(bottom: 12),
|
||||
padding: HtmlPaddings.only(left: 16),
|
||||
),
|
||||
"li": Style(
|
||||
margin: Margins.only(bottom: 4),
|
||||
color: defaultTextColor,
|
||||
),
|
||||
"strong, b": Style(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black,
|
||||
),
|
||||
"em, i": Style(fontStyle: FontStyle.italic),
|
||||
"code": Style(
|
||||
backgroundColor: Colors.grey.shade100,
|
||||
padding: HtmlPaddings.symmetric(horizontal: 4, vertical: 2),
|
||||
fontFamily: 'monospace',
|
||||
),
|
||||
"pre": Style(
|
||||
backgroundColor: Colors.grey.shade100,
|
||||
padding: HtmlPaddings.all(12),
|
||||
margin: Margins.only(bottom: 12),
|
||||
),
|
||||
"blockquote": Style(
|
||||
padding: HtmlPaddings.only(left: 16),
|
||||
margin: Margins.only(left: 8, bottom: 12),
|
||||
fontStyle: FontStyle.italic,
|
||||
color: Colors.grey.shade700,
|
||||
),
|
||||
"a": Style(
|
||||
color: Colors.blue,
|
||||
textDecoration: TextDecoration.underline,
|
||||
),
|
||||
"img": Style(width: Width(defaultImageWidth)),
|
||||
},
|
||||
onLinkTap: onLinkTap ?? ((url, attributes, element) async {
|
||||
if (url != null) {
|
||||
try {
|
||||
final uri = Uri.parse(url);
|
||||
if (await canLaunchUrl(uri)) {
|
||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('Error launching URL: $e');
|
||||
}
|
||||
}
|
||||
}) as OnTap,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import 'package:eatvio_app/core/enums/complained_content.dart';
|
||||
import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_popup.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/core/widgets/markdown_html_widget.dart';
|
||||
import 'package:eatvio_app/features/blog_post/presentation/cubit/blog_post_cubit.dart';
|
||||
import 'package:eatvio_app/features/blog_post/presentation/cubit/blog_post_state.dart';
|
||||
import 'package:eatvio_app/core/comments/comments_cubit/comments_cubit.dart';
|
||||
@@ -12,13 +13,11 @@ import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/comments_widget.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
import 'package:markdown/markdown.dart' as md;
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class BlogPostScreen extends StatefulWidget {
|
||||
final int id;
|
||||
@@ -126,7 +125,7 @@ class _BlogPostScreenState extends State<BlogPostScreen> {
|
||||
// убираем true, чтобы padding учитывался корректно
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
||||
// вертикальный паддинг увеличен
|
||||
hintText: 'Комментарий',
|
||||
hintText: S.of(context).comment_hint,
|
||||
hintStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w400, height: 1.2, color: Color(0xFFAEAEB2)),
|
||||
filled: true,
|
||||
border: OutlineInputBorder(
|
||||
@@ -237,111 +236,11 @@ class _BlogPostScreenState extends State<BlogPostScreen> {
|
||||
if (blogPostState.blogPostModel?.description.isNotEmpty ?? false)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
// Автоматически преобразуем URL в markdown ссылки
|
||||
String description = blogPostState.blogPostModel!.description;
|
||||
|
||||
// Сначала исправляем неправильный синтаксис markdown ссылок, где URL в тексте, а не в href
|
||||
// Например: [http://example.com](url) -> [http://example.com](http://example.com)
|
||||
final wrongLinkRegex = RegExp(r'\[(https?://[^\]]+|www\.[^\]]+)\]\(([^\)]+)\)');
|
||||
description = description.replaceAllMapped(wrongLinkRegex, (match) {
|
||||
final urlInText = match.group(1)!;
|
||||
// Если текст ссылки является URL, используем его как href
|
||||
if (!urlInText.startsWith('http://') && !urlInText.startsWith('https://') && !urlInText.startsWith('www.')) {
|
||||
return match.group(0)!; // Оставляем как есть, если это не URL
|
||||
}
|
||||
final fullUrl = urlInText.startsWith('www.') ? 'https://$urlInText' : urlInText;
|
||||
// Используем URL как href, а текст ссылки - это сам URL
|
||||
return '[$urlInText]($fullUrl)';
|
||||
});
|
||||
|
||||
// Теперь находим все существующие markdown ссылки и их позиции
|
||||
final linkRegex = RegExp(r'\[([^\]]+)\]\(([^\)]+)\)');
|
||||
final existingLinks = <_LinkRange>[];
|
||||
|
||||
for (final linkMatch in linkRegex.allMatches(description)) {
|
||||
existingLinks.add(_LinkRange(linkMatch.start, linkMatch.end));
|
||||
}
|
||||
|
||||
// Регулярное выражение для поиска URL (http://, https://, www.)
|
||||
final urlRegex = RegExp(r'(https?://[^\s\)]+|www\.[^\s\)]+)', caseSensitive: false);
|
||||
|
||||
// Заменяем URL на markdown ссылки, если они еще не являются ссылками
|
||||
String result = description;
|
||||
int offset = 0;
|
||||
|
||||
for (final urlMatch in urlRegex.allMatches(description)) {
|
||||
// Проверяем, не находится ли URL внутри существующей markdown ссылки
|
||||
bool isInsideLink = existingLinks.any((link) => urlMatch.start >= link.start && urlMatch.end <= link.end);
|
||||
|
||||
if (!isInsideLink) {
|
||||
final url = urlMatch.group(0)!;
|
||||
final fullUrl = url.startsWith('www.') ? 'https://$url' : url;
|
||||
final replacement = '[$url]($fullUrl)';
|
||||
result = result.replaceRange(urlMatch.start + offset, urlMatch.end + offset, replacement);
|
||||
offset += replacement.length - url.length;
|
||||
}
|
||||
}
|
||||
|
||||
description = result;
|
||||
|
||||
// Гарантируем, что жирный текст будет распознан
|
||||
// Заменяем **текст** на <b>текст</b> вручную для надежности
|
||||
final boldRegex = RegExp(r'\*\*([^*]+)\*\*');
|
||||
description = description.replaceAllMapped(boldRegex, (match) {
|
||||
return '<b>${match.group(1)}</b>';
|
||||
});
|
||||
|
||||
final htmlData = md.markdownToHtml(
|
||||
description,
|
||||
extensionSet: md.ExtensionSet.gitHubFlavored,
|
||||
);
|
||||
return Html(
|
||||
data: htmlData,
|
||||
style: {
|
||||
"body": Style(margin: Margins.zero, padding: HtmlPaddings.zero, fontSize: FontSize(16), lineHeight: const LineHeight(1.5), color: Colors.black87),
|
||||
"p": Style(margin: Margins.only(bottom: 12), color: Colors.black87),
|
||||
"b, strong": Style(fontWeight: FontWeight.bold, color: Colors.black),
|
||||
"h1, h2, h3, h4, h5, h6": Style(margin: Margins.only(top: 16, bottom: 8), color: Colors.black, fontWeight: FontWeight.bold),
|
||||
"h1": Style(fontSize: FontSize(24)),
|
||||
"h2": Style(fontSize: FontSize(20)),
|
||||
"h3": Style(fontSize: FontSize(18)),
|
||||
"ul, ol": Style(margin: Margins.only(bottom: 12), padding: HtmlPaddings.only(left: 16)),
|
||||
"li": Style(margin: Margins.only(bottom: 4), color: Colors.black87),
|
||||
"strong, b": Style(fontWeight: FontWeight.bold, color: Colors.black),
|
||||
"em, i": Style(fontStyle: FontStyle.italic),
|
||||
"code": Style(
|
||||
backgroundColor: Colors.grey.shade100,
|
||||
padding: HtmlPaddings.symmetric(horizontal: 4, vertical: 2),
|
||||
fontFamily: 'monospace',
|
||||
),
|
||||
"pre": Style(backgroundColor: Colors.grey.shade100, padding: HtmlPaddings.all(12), margin: Margins.only(bottom: 12)),
|
||||
"blockquote": Style(
|
||||
padding: HtmlPaddings.only(left: 16),
|
||||
margin: Margins.only(left: 8, bottom: 12),
|
||||
fontStyle: FontStyle.italic,
|
||||
color: Colors.grey.shade700,
|
||||
),
|
||||
"a": Style(color: Colors.blue, textDecoration: TextDecoration.underline),
|
||||
"img": Style(width: Width(MediaQuery.of(context).size.width - 32)),
|
||||
},
|
||||
onLinkTap: (url, attributes, element) async {
|
||||
debugPrint('Link tapped: $url');
|
||||
if (url != null) {
|
||||
try {
|
||||
final uri = Uri.parse(url);
|
||||
if (await canLaunchUrl(uri)) {
|
||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
} else {
|
||||
debugPrint('Cannot launch URL: $url');
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('Error launching URL: $e');
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
child: MarkdownHtmlWidget(
|
||||
markdownText: blogPostState.blogPostModel!.description,
|
||||
onLinkTap: (url, attributes, element) {
|
||||
debugPrint('Link tapped: $url');
|
||||
return;
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -445,10 +344,3 @@ class _BlogPostScreenState extends State<BlogPostScreen> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _LinkRange {
|
||||
final int start;
|
||||
final int end;
|
||||
|
||||
_LinkRange(this.start, this.end);
|
||||
}
|
||||
|
||||
@@ -3,11 +3,10 @@ import 'dart:math' as math;
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/utils/markdown_utils.dart';
|
||||
import 'package:eatvio_app/core/widgets/markdown_html_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
import 'package:markdown/markdown.dart' as md;
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class ExpandableText extends StatefulWidget {
|
||||
final String text;
|
||||
@@ -57,60 +56,9 @@ class _ExpandableTextState extends State<ExpandableText> {
|
||||
});
|
||||
}
|
||||
|
||||
String _processMarkdown(String text) {
|
||||
// Автоматически преобразуем URL в markdown ссылки
|
||||
// Сначала исправляем неправильный синтаксис markdown ссылок
|
||||
final wrongLinkRegex = RegExp(r'\[(https?://[^\]]+|www\.[^\]]+)\]\(([^\)]+)\)');
|
||||
text = text.replaceAllMapped(wrongLinkRegex, (match) {
|
||||
final urlInText = match.group(1)!;
|
||||
if (!urlInText.startsWith('http://') && !urlInText.startsWith('https://') && !urlInText.startsWith('www.')) {
|
||||
return match.group(0)!;
|
||||
}
|
||||
final fullUrl = urlInText.startsWith('www.') ? 'https://$urlInText' : urlInText;
|
||||
return '[$urlInText]($fullUrl)';
|
||||
});
|
||||
|
||||
final linkRegex = RegExp(r'\[([^\]]+)\]\(([^\)]+)\)');
|
||||
final existingLinks = <_LinkRange>[];
|
||||
for (final linkMatch in linkRegex.allMatches(text)) {
|
||||
existingLinks.add(_LinkRange(linkMatch.start, linkMatch.end));
|
||||
}
|
||||
final urlRegex = RegExp(r'(https?://[^\s\)]+|www\.[^\s\)]+)', caseSensitive: false);
|
||||
String result = text;
|
||||
int offset = 0;
|
||||
for (final urlMatch in urlRegex.allMatches(text)) {
|
||||
bool isInsideLink = existingLinks.any((link) =>
|
||||
urlMatch.start >= link.start && urlMatch.end <= link.end);
|
||||
if (!isInsideLink) {
|
||||
final url = urlMatch.group(0)!;
|
||||
final fullUrl = url.startsWith('www.') ? 'https://$url' : url;
|
||||
final replacement = '[$url]($fullUrl)';
|
||||
result = result.replaceRange(
|
||||
urlMatch.start + offset,
|
||||
urlMatch.end + offset,
|
||||
replacement,
|
||||
);
|
||||
offset += replacement.length - url.length;
|
||||
}
|
||||
}
|
||||
|
||||
// Гарантируем, что жирный текст будет распознан
|
||||
final boldRegex = RegExp(r'\*\*([^*]+)\*\*');
|
||||
result = result.replaceAllMapped(boldRegex, (match) {
|
||||
return '<b>${match.group(1)}</b>';
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
final processedText = _processMarkdown(widget.text);
|
||||
final htmlData = md.markdownToHtml(
|
||||
processedText,
|
||||
extensionSet: md.ExtensionSet.gitHubFlavored,
|
||||
);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -127,49 +75,11 @@ class _ExpandableTextState extends State<ExpandableText> {
|
||||
constraints: BoxConstraints(
|
||||
maxHeight: isExpanded ? double.infinity : (widget.maxLines * (TextStyles.textMMediumAuto.fontSize ?? 16) * 1.5),
|
||||
),
|
||||
child: Html(
|
||||
child: MarkdownHtmlWidget(
|
||||
key: _textKey,
|
||||
data: htmlData,
|
||||
style: {
|
||||
"body": Style(
|
||||
margin: Margins.zero,
|
||||
padding: HtmlPaddings.zero,
|
||||
fontSize: FontSize(TextStyles.textMMediumAuto.fontSize ?? 16),
|
||||
lineHeight: const LineHeight(1.5),
|
||||
),
|
||||
"p": Style(margin: Margins.only(bottom: 12), color: appTheme.black),
|
||||
"b, strong": Style(fontWeight: FontWeight.bold, color: appTheme.black),
|
||||
"h1, h2, h3, h4, h5, h6": Style(margin: Margins.only(top: 16, bottom: 8), color: appTheme.black, fontWeight: FontWeight.bold),
|
||||
"h1": Style(fontSize: FontSize(24)),
|
||||
"h2": Style(fontSize: FontSize(20)),
|
||||
"h3": Style(fontSize: FontSize(18)),
|
||||
"ul, ol": Style(margin: Margins.only(bottom: 12), padding: HtmlPaddings.only(left: 16)),
|
||||
"li": Style(margin: Margins.only(bottom: 4), color: appTheme.black),
|
||||
"strong, b": Style(fontWeight: FontWeight.bold, color: appTheme.black),
|
||||
"em, i": Style(fontStyle: FontStyle.italic),
|
||||
"code": Style(
|
||||
backgroundColor: Colors.grey.shade100,
|
||||
padding: HtmlPaddings.symmetric(horizontal: 4, vertical: 2),
|
||||
fontFamily: 'monospace',
|
||||
),
|
||||
"pre": Style(backgroundColor: Colors.grey.shade100, padding: HtmlPaddings.all(12), margin: Margins.only(bottom: 12)),
|
||||
"blockquote": Style(
|
||||
padding: HtmlPaddings.only(left: 16),
|
||||
margin: Margins.only(left: 8, bottom: 12),
|
||||
fontStyle: FontStyle.italic,
|
||||
color: Colors.grey.shade700,
|
||||
),
|
||||
"a": Style(color: Colors.blue, textDecoration: TextDecoration.underline),
|
||||
"img": Style(width: Width(MediaQuery.of(context).size.width - 32)),
|
||||
},
|
||||
onLinkTap: (url, attributes, element) async {
|
||||
if (url != null) {
|
||||
final uri = Uri.parse(url);
|
||||
if (await canLaunchUrl(uri)) {
|
||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
}
|
||||
}
|
||||
},
|
||||
markdownText: widget.text,
|
||||
fontSize: TextStyles.textMMediumAuto.fontSize ?? 16,
|
||||
textColor: appTheme.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -222,9 +132,3 @@ class _ExpandableTextState extends State<ExpandableText> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _LinkRange {
|
||||
final int start;
|
||||
final int end;
|
||||
_LinkRange(this.start, this.end);
|
||||
}
|
||||
|
||||
@@ -7,17 +7,16 @@ import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_popup.dart';
|
||||
import 'package:eatvio_app/core/widgets/feed_icon_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/markdown_html_widget.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/pages/photo_view_screen.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_state.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/subscribe_button_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
import 'package:markdown/markdown.dart' as md;
|
||||
|
||||
class BlogPostWidget extends StatefulWidget {
|
||||
final int index;
|
||||
@@ -162,47 +161,8 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
description = description.substring(0, cutPoint);
|
||||
}
|
||||
|
||||
// Гарантируем, что жирный текст будет распознан
|
||||
final boldRegex = RegExp(r'\*\*([^*]+)\*\*');
|
||||
description = description.replaceAllMapped(boldRegex, (match) {
|
||||
return '<b>${match.group(1)}</b>';
|
||||
});
|
||||
|
||||
// Конвертируем markdown в HTML
|
||||
String htmlData = md.markdownToHtml(
|
||||
description,
|
||||
extensionSet: md.ExtensionSet.gitHubFlavored,
|
||||
);
|
||||
|
||||
return Html(
|
||||
data: htmlData,
|
||||
style: {
|
||||
"body": Style(margin: Margins.zero, padding: HtmlPaddings.zero, fontSize: FontSize(16), lineHeight: const LineHeight(1.5), color: Colors.black87),
|
||||
"p": Style(margin: Margins.only(bottom: 12), color: Colors.black87),
|
||||
"b, strong": Style(fontWeight: FontWeight.bold, color: Colors.black),
|
||||
"h1, h2, h3, h4, h5, h6": Style(margin: Margins.only(top: 16, bottom: 8), color: Colors.black, fontWeight: FontWeight.bold),
|
||||
"h1": Style(fontSize: FontSize(24)),
|
||||
"h2": Style(fontSize: FontSize(20)),
|
||||
"h3": Style(fontSize: FontSize(18)),
|
||||
"ul, ol": Style(margin: Margins.only(bottom: 12), padding: HtmlPaddings.only(left: 16)),
|
||||
"li": Style(margin: Margins.only(bottom: 4), color: Colors.black87),
|
||||
"strong, b": Style(fontWeight: FontWeight.bold, color: Colors.black),
|
||||
"em, i": Style(fontStyle: FontStyle.italic),
|
||||
"code": Style(
|
||||
backgroundColor: Colors.grey.shade100,
|
||||
padding: HtmlPaddings.symmetric(horizontal: 4, vertical: 2),
|
||||
fontFamily: 'monospace',
|
||||
),
|
||||
"pre": Style(backgroundColor: Colors.grey.shade100, padding: HtmlPaddings.all(12), margin: Margins.only(bottom: 12)),
|
||||
"blockquote": Style(
|
||||
padding: HtmlPaddings.only(left: 16),
|
||||
margin: Margins.only(left: 8, bottom: 12),
|
||||
fontStyle: FontStyle.italic,
|
||||
color: Colors.grey.shade700,
|
||||
),
|
||||
"a": Style(color: Colors.blue, textDecoration: TextDecoration.underline),
|
||||
"img": Style(width: Width(MediaQuery.of(context).size.width - 32)),
|
||||
},
|
||||
return MarkdownHtmlWidget(
|
||||
markdownText: description,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:eatvio_app/core/widgets/bookmark_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_popup.dart';
|
||||
import 'package:eatvio_app/core/widgets/info_row.dart';
|
||||
import 'package:eatvio_app/core/widgets/feed_icon_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/markdown_html_widget.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.dart';
|
||||
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
@@ -15,12 +16,9 @@ import 'package:eatvio_app/features/feed/presentation/bloc/plans_cubit/plans_cub
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
import 'package:markdown/markdown.dart' as md;
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class PlanWidget extends StatefulWidget {
|
||||
final PlanModel plan;
|
||||
@@ -117,96 +115,11 @@ class _PlanWidgetState extends State<PlanWidget> {
|
||||
const SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
String details = widget.plan.details.length > 200
|
||||
? '${widget.plan.details.substring(0, 200)}...'
|
||||
: widget.plan.details;
|
||||
// Автоматически преобразуем URL в markdown ссылки
|
||||
// Сначала исправляем неправильный синтаксис markdown ссылок
|
||||
final wrongLinkRegex = RegExp(r'\[(https?://[^\]]+|www\.[^\]]+)\]\(([^\)]+)\)');
|
||||
details = details.replaceAllMapped(wrongLinkRegex, (match) {
|
||||
final urlInText = match.group(1)!;
|
||||
if (!urlInText.startsWith('http://') && !urlInText.startsWith('https://') && !urlInText.startsWith('www.')) {
|
||||
return match.group(0)!;
|
||||
}
|
||||
final fullUrl = urlInText.startsWith('www.') ? 'https://$urlInText' : urlInText;
|
||||
return '[$urlInText]($fullUrl)';
|
||||
});
|
||||
|
||||
final linkRegex = RegExp(r'\[([^\]]+)\]\(([^\)]+)\)');
|
||||
final existingLinks = <_LinkRange>[];
|
||||
for (final linkMatch in linkRegex.allMatches(details)) {
|
||||
existingLinks.add(_LinkRange(linkMatch.start, linkMatch.end));
|
||||
}
|
||||
final urlRegex = RegExp(r'(https?://[^\s\)]+|www\.[^\s\)]+)', caseSensitive: false);
|
||||
String result = details;
|
||||
int offset = 0;
|
||||
for (final urlMatch in urlRegex.allMatches(details)) {
|
||||
bool isInsideLink = existingLinks.any((link) =>
|
||||
urlMatch.start >= link.start && urlMatch.end <= link.end);
|
||||
if (!isInsideLink) {
|
||||
final url = urlMatch.group(0)!;
|
||||
final fullUrl = url.startsWith('www.') ? 'https://$url' : url;
|
||||
final replacement = '[$url]($fullUrl)';
|
||||
result = result.replaceRange(
|
||||
urlMatch.start + offset,
|
||||
urlMatch.end + offset,
|
||||
replacement,
|
||||
);
|
||||
offset += replacement.length - url.length;
|
||||
}
|
||||
}
|
||||
details = result;
|
||||
|
||||
// Гарантируем, что жирный текст будет распознан
|
||||
final boldRegex = RegExp(r'\*\*([^*]+)\*\*');
|
||||
details = details.replaceAllMapped(boldRegex, (match) {
|
||||
return '<b>${match.group(1)}</b>';
|
||||
});
|
||||
|
||||
return Html(
|
||||
data: md.markdownToHtml(
|
||||
details,
|
||||
extensionSet: md.ExtensionSet.gitHubFlavored,
|
||||
),
|
||||
style: {
|
||||
"body": Style(margin: Margins.zero, padding: HtmlPaddings.zero, fontSize: FontSize(16), lineHeight: const LineHeight(1.5)),
|
||||
"p": Style(margin: Margins.only(bottom: 12), color: appTheme.black),
|
||||
"b, strong": Style(fontWeight: FontWeight.bold, color: appTheme.black),
|
||||
"h1, h2, h3, h4, h5, h6": Style(margin: Margins.only(top: 16, bottom: 8), color: appTheme.black, fontWeight: FontWeight.bold),
|
||||
"h1": Style(fontSize: FontSize(24)),
|
||||
"h2": Style(fontSize: FontSize(20)),
|
||||
"h3": Style(fontSize: FontSize(18)),
|
||||
"ul, ol": Style(margin: Margins.only(bottom: 12), padding: HtmlPaddings.only(left: 16)),
|
||||
"li": Style(margin: Margins.only(bottom: 4), color: appTheme.black),
|
||||
"strong, b": Style(fontWeight: FontWeight.bold, color: appTheme.black),
|
||||
"em, i": Style(fontStyle: FontStyle.italic),
|
||||
"code": Style(
|
||||
backgroundColor: Colors.grey.shade100,
|
||||
padding: HtmlPaddings.symmetric(horizontal: 4, vertical: 2),
|
||||
fontFamily: 'monospace',
|
||||
),
|
||||
"pre": Style(backgroundColor: Colors.grey.shade100, padding: HtmlPaddings.all(12), margin: Margins.only(bottom: 12)),
|
||||
"blockquote": Style(
|
||||
padding: HtmlPaddings.only(left: 16),
|
||||
margin: Margins.only(left: 8, bottom: 12),
|
||||
fontStyle: FontStyle.italic,
|
||||
color: Colors.grey.shade700,
|
||||
),
|
||||
"a": Style(color: Colors.blue, textDecoration: TextDecoration.underline),
|
||||
"img": Style(width: Width(MediaQuery.of(context).size.width - 32)),
|
||||
},
|
||||
onLinkTap: (url, attributes, element) async {
|
||||
if (url != null) {
|
||||
final uri = Uri.parse(url);
|
||||
if (await canLaunchUrl(uri)) {
|
||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
child: MarkdownHtmlWidget(
|
||||
markdownText: widget.plan.details.length > 200
|
||||
? '${widget.plan.details.substring(0, 200)}...'
|
||||
: widget.plan.details,
|
||||
textColor: appTheme.black,
|
||||
),
|
||||
),
|
||||
if (widget.plan.details.length > 200)
|
||||
@@ -320,9 +233,3 @@ class _PlanWidgetState extends State<PlanWidget> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _LinkRange {
|
||||
final int start;
|
||||
final int end;
|
||||
_LinkRange(this.start, this.end);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:intl/message_lookup_by_library.dart';
|
||||
import 'package:intl/src/intl_helpers.dart';
|
||||
@@ -21,8 +20,8 @@ import 'messages_ru.dart' as messages_ru;
|
||||
|
||||
typedef Future<dynamic> LibraryLoader();
|
||||
Map<String, LibraryLoader> _deferredLibraries = {
|
||||
'en': () => new SynchronousFuture(null),
|
||||
'ru': () => new SynchronousFuture(null),
|
||||
'en': () => new Future.value(null),
|
||||
'ru': () => new Future.value(null),
|
||||
};
|
||||
|
||||
MessageLookupByLibrary? _findExact(String localeName) {
|
||||
@@ -37,20 +36,19 @@ MessageLookupByLibrary? _findExact(String localeName) {
|
||||
}
|
||||
|
||||
/// User programs should call this before using [localeName] for messages.
|
||||
Future<bool> initializeMessages(String localeName) {
|
||||
Future<bool> initializeMessages(String localeName) async {
|
||||
var availableLocale = Intl.verifiedLocale(
|
||||
localeName,
|
||||
(locale) => _deferredLibraries[locale] != null,
|
||||
onFailure: (_) => null,
|
||||
);
|
||||
onFailure: (_) => null);
|
||||
if (availableLocale == null) {
|
||||
return new SynchronousFuture(false);
|
||||
return new Future.value(false);
|
||||
}
|
||||
var lib = _deferredLibraries[availableLocale];
|
||||
lib == null ? new SynchronousFuture(false) : lib();
|
||||
await (lib == null ? new Future.value(false) : lib());
|
||||
initializeInternalMessageLookup(() => new CompositeMessageLookup());
|
||||
messageLookup.addLocale(availableLocale, _findGeneratedMessagesFor);
|
||||
return new SynchronousFuture(true);
|
||||
return new Future.value(true);
|
||||
}
|
||||
|
||||
bool _messagesExistFor(String locale) {
|
||||
@@ -62,11 +60,8 @@ bool _messagesExistFor(String locale) {
|
||||
}
|
||||
|
||||
MessageLookupByLibrary? _findGeneratedMessagesFor(String locale) {
|
||||
var actualLocale = Intl.verifiedLocale(
|
||||
locale,
|
||||
_messagesExistFor,
|
||||
onFailure: (_) => null,
|
||||
);
|
||||
var actualLocale = Intl.verifiedLocale(locale, _messagesExistFor,
|
||||
onFailure: (_) => null);
|
||||
if (actualLocale == null) return null;
|
||||
return _findExact(actualLocale);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,8 +7,7 @@
|
||||
// ignore_for_file:unnecessary_brace_in_string_interps, unnecessary_new
|
||||
// ignore_for_file:prefer_single_quotes,comment_references, directives_ordering
|
||||
// ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases
|
||||
// ignore_for_file:unused_import, file_names, avoid_escaping_inner_quotes
|
||||
// ignore_for_file:unnecessary_string_interpolations, unnecessary_string_escapes
|
||||
// ignore_for_file:unused_import, file_names
|
||||
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:intl/message_lookup_by_library.dart';
|
||||
@@ -21,362 +20,223 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
String get localeName => 'ru';
|
||||
|
||||
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
|
||||
"Moscow": MessageLookupByLibrary.simpleMessage("Москва"),
|
||||
"Russia": MessageLookupByLibrary.simpleMessage("Россия"),
|
||||
"about_diet": MessageLookupByLibrary.simpleMessage("Об этой диете"),
|
||||
"about_plan": MessageLookupByLibrary.simpleMessage("Об этом плане"),
|
||||
"active": MessageLookupByLibrary.simpleMessage("Активен"),
|
||||
"active_diet_state": MessageLookupByLibrary.simpleMessage("Активная"),
|
||||
"add": MessageLookupByLibrary.simpleMessage("Добавить"),
|
||||
"add_cover": MessageLookupByLibrary.simpleMessage("Добавьте обложку"),
|
||||
"add_measure": MessageLookupByLibrary.simpleMessage("Добавить замер"),
|
||||
"adding_plan": MessageLookupByLibrary.simpleMessage("Добавление плана"),
|
||||
"additional_information": MessageLookupByLibrary.simpleMessage(
|
||||
"Дополнительная информация",
|
||||
),
|
||||
"admin": MessageLookupByLibrary.simpleMessage("Админ"),
|
||||
"all": MessageLookupByLibrary.simpleMessage("Все"),
|
||||
"allergies_presence": MessageLookupByLibrary.simpleMessage(
|
||||
"Наличие аллергии",
|
||||
),
|
||||
"another_form_of_comment": MessageLookupByLibrary.simpleMessage(
|
||||
"комментария",
|
||||
),
|
||||
"another_form_of_day": MessageLookupByLibrary.simpleMessage("дня"),
|
||||
"answer": MessageLookupByLibrary.simpleMessage("Ответить"),
|
||||
"archived": MessageLookupByLibrary.simpleMessage("В архиве"),
|
||||
"authentificate": MessageLookupByLibrary.simpleMessage("Войти"),
|
||||
"average_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
"Средние показатели давления:",
|
||||
),
|
||||
"bodymass_chart": MessageLookupByLibrary.simpleMessage("График ИМТ"),
|
||||
"by_default": MessageLookupByLibrary.simpleMessage("По умолчанию"),
|
||||
"calories": MessageLookupByLibrary.simpleMessage("Калории"),
|
||||
"carb_type": MessageLookupByLibrary.simpleMessage("Мучное"),
|
||||
"carb_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы.",
|
||||
),
|
||||
"carbohydrates": MessageLookupByLibrary.simpleMessage("Углеводы"),
|
||||
"chat": MessageLookupByLibrary.simpleMessage("Чат"),
|
||||
"chest": MessageLookupByLibrary.simpleMessage("Грудь"),
|
||||
"chest_circumference": MessageLookupByLibrary.simpleMessage("Обхват груди"),
|
||||
"choose_diet_duration": MessageLookupByLibrary.simpleMessage(
|
||||
"Выберите срок диеты",
|
||||
),
|
||||
"choose_plan_duration": MessageLookupByLibrary.simpleMessage(
|
||||
"Выберите срок плана",
|
||||
),
|
||||
"choose_start_diet_date": MessageLookupByLibrary.simpleMessage(
|
||||
"Выберите дату старты диеты. Она отобразиться у Вас в дневнике",
|
||||
),
|
||||
"circumference_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Все замеры обязательны к заполнению",
|
||||
),
|
||||
"circumference_is_not_a_number": MessageLookupByLibrary.simpleMessage(
|
||||
"Все замеры должны быть числами",
|
||||
),
|
||||
"circumferences_chart": MessageLookupByLibrary.simpleMessage(
|
||||
"График обхватов",
|
||||
),
|
||||
"city": MessageLookupByLibrary.simpleMessage("Город"),
|
||||
"city_of_living": MessageLookupByLibrary.simpleMessage("Город проживания"),
|
||||
"comfort": MessageLookupByLibrary.simpleMessage("Комфорт"),
|
||||
"comment": MessageLookupByLibrary.simpleMessage("комментарий"),
|
||||
"comments": MessageLookupByLibrary.simpleMessage("Комментарии"),
|
||||
"comments_plural": MessageLookupByLibrary.simpleMessage("комментариев"),
|
||||
"complain": MessageLookupByLibrary.simpleMessage("Пожаловаться"),
|
||||
"continueButton": MessageLookupByLibrary.simpleMessage("Продолжить"),
|
||||
"continue_": MessageLookupByLibrary.simpleMessage("Продолжить"),
|
||||
"copied": MessageLookupByLibrary.simpleMessage("cкопирован"),
|
||||
"copy_link": MessageLookupByLibrary.simpleMessage("Скопировать ссылку"),
|
||||
"country": MessageLookupByLibrary.simpleMessage("Страна"),
|
||||
"create_diet": MessageLookupByLibrary.simpleMessage("Создание диеты"),
|
||||
"customer_price": MessageLookupByLibrary.simpleMessage(
|
||||
"Цена для покупателя",
|
||||
),
|
||||
"date_of_birth": MessageLookupByLibrary.simpleMessage("Дата рождения"),
|
||||
"day": MessageLookupByLibrary.simpleMessage("День"),
|
||||
"days": MessageLookupByLibrary.simpleMessage("дней"),
|
||||
"deleted": MessageLookupByLibrary.simpleMessage("Удалена"),
|
||||
"diary": MessageLookupByLibrary.simpleMessage("Дневник"),
|
||||
"diet": MessageLookupByLibrary.simpleMessage("Диета"),
|
||||
"diet_author": MessageLookupByLibrary.simpleMessage("Автор диеты"),
|
||||
"diet_plan": MessageLookupByLibrary.simpleMessage("План диеты"),
|
||||
"diet_state": MessageLookupByLibrary.simpleMessage("Статус диеты"),
|
||||
"diet_type": MessageLookupByLibrary.simpleMessage("Тип диеты"),
|
||||
"do_you_have_hypertension_tendency": MessageLookupByLibrary.simpleMessage(
|
||||
"Есть ли у вас гипертония?",
|
||||
),
|
||||
"do_you_have_hypotension_tendency": MessageLookupByLibrary.simpleMessage(
|
||||
"Есть ли у вас гипотония?",
|
||||
),
|
||||
"do_you_take_pills": MessageLookupByLibrary.simpleMessage(
|
||||
"Принимаете ли вы лекарства или бады?",
|
||||
),
|
||||
"down_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
"Нижние показатели давления:",
|
||||
),
|
||||
"draft": MessageLookupByLibrary.simpleMessage("Черновик"),
|
||||
"drafted": MessageLookupByLibrary.simpleMessage("Черновики"),
|
||||
"eating_behavior": MessageLookupByLibrary.simpleMessage(
|
||||
"Пищевое поведение",
|
||||
),
|
||||
"eating_behavior_type": MessageLookupByLibrary.simpleMessage(
|
||||
"Формирование пищевого поведения",
|
||||
),
|
||||
"eating_behavior_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Формирование здорового пищевого поведения — это процесс, который включает в себя изменение привычек и отношения к еде. Он направлен на то, чтобы помочь людям научиться правильно питаться и поддерживать здоровый образ жизни.Основные принципы формирования здорового пищевого поведения: \n● Разнообразие продуктов; \n● Сбалансированный рацион; \n● Питьевой режим; \n● Ограничение вредных продуктов; \n● Регулярные приёмы пищи; \n● Умеренность;Осознанное питание; \n● Физическая активность;",
|
||||
),
|
||||
"economy": MessageLookupByLibrary.simpleMessage("Эконом"),
|
||||
"edit": MessageLookupByLibrary.simpleMessage("Редактировать"),
|
||||
"email": MessageLookupByLibrary.simpleMessage("Электронная почта"),
|
||||
"email_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Необходимо ввести адрес электронной почты",
|
||||
),
|
||||
"email_invalid": MessageLookupByLibrary.simpleMessage(
|
||||
"Некорректный адрес электронной почты",
|
||||
),
|
||||
"enter_additional_information": MessageLookupByLibrary.simpleMessage(
|
||||
"Введите любую дополнительную информацию на своё усмотрение:",
|
||||
),
|
||||
"enter_diet_description": MessageLookupByLibrary.simpleMessage(
|
||||
"Введите описание диеты",
|
||||
),
|
||||
"enter_diet_name": MessageLookupByLibrary.simpleMessage(
|
||||
"Выведите название диеты",
|
||||
),
|
||||
"enter_information": MessageLookupByLibrary.simpleMessage(
|
||||
"Введите информацию...",
|
||||
),
|
||||
"exit": MessageLookupByLibrary.simpleMessage("Выйти"),
|
||||
"expand": MessageLookupByLibrary.simpleMessage("Показать полностью"),
|
||||
"fats": MessageLookupByLibrary.simpleMessage("Жиры"),
|
||||
"favorite_foods": MessageLookupByLibrary.simpleMessage("Любимые продукты"),
|
||||
"favorite_unfavorite_foods": MessageLookupByLibrary.simpleMessage(
|
||||
"Ваши любимые/нелюбимые продукты питания?",
|
||||
),
|
||||
"female": MessageLookupByLibrary.simpleMessage("Женский"),
|
||||
"fill_in_information": MessageLookupByLibrary.simpleMessage(
|
||||
"Заполните информацию:",
|
||||
),
|
||||
"finish": MessageLookupByLibrary.simpleMessage("Завершить"),
|
||||
"first_name": MessageLookupByLibrary.simpleMessage("Имя"),
|
||||
"first_name_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Имя обязательно для заполнения",
|
||||
),
|
||||
"first_name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В имени должен быть минимум 1 символ",
|
||||
),
|
||||
"fit_type": MessageLookupByLibrary.simpleMessage("Поддержание формы"),
|
||||
"fit_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"План питания для поддержания формы сбалансированный и разнообразный, чтобы обеспечить организм всеми необходимыми питательными веществами. Общие принципы: \n● Дробное питание; \n● Разнообразие продуктов; \n● Контроль порций; \n● Питьевой режим; \n● Ограничение вредных продуктов;",
|
||||
),
|
||||
"fitness": MessageLookupByLibrary.simpleMessage("Поддержка формы"),
|
||||
"from": MessageLookupByLibrary.simpleMessage("от"),
|
||||
"from_a_to_z": MessageLookupByLibrary.simpleMessage("Название: А-Я"),
|
||||
"from_z_to_a": MessageLookupByLibrary.simpleMessage("Название: Я-А"),
|
||||
"gallery": MessageLookupByLibrary.simpleMessage("Галерея"),
|
||||
"gr": MessageLookupByLibrary.simpleMessage("гр"),
|
||||
"grams": MessageLookupByLibrary.simpleMessage("гр"),
|
||||
"height_measurements": MessageLookupByLibrary.simpleMessage("Замер роста"),
|
||||
"hide": MessageLookupByLibrary.simpleMessage("Свернуть"),
|
||||
"hip_circumference": MessageLookupByLibrary.simpleMessage("Обхват бедер"),
|
||||
"hips": MessageLookupByLibrary.simpleMessage("Бедра"),
|
||||
"in_progress": MessageLookupByLibrary.simpleMessage("В процессе"),
|
||||
"inactive_diet_state": MessageLookupByLibrary.simpleMessage("Черновик"),
|
||||
"infoAboutOrder": MessageLookupByLibrary.simpleMessage(
|
||||
"Информация о заказе",
|
||||
),
|
||||
"initial_measurements": MessageLookupByLibrary.simpleMessage(
|
||||
"Первичные замеры",
|
||||
),
|
||||
"label": MessageLookupByLibrary.simpleMessage("Название"),
|
||||
"language": MessageLookupByLibrary.simpleMessage("Язык"),
|
||||
"last_name": MessageLookupByLibrary.simpleMessage("Фамилия"),
|
||||
"last_name_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Фамилия обязательна для заполнения",
|
||||
),
|
||||
"last_name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В фамилии должен быть минимум 6 символов",
|
||||
),
|
||||
"lbl_english": MessageLookupByLibrary.simpleMessage("English"),
|
||||
"light_type": MessageLookupByLibrary.simpleMessage("Легкая"),
|
||||
"light_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"С некоторыми видами диет можно употреблять алкоголь в умеренных количествах. Рекомендуется совмещать вместе с низкокалорийными закусками.",
|
||||
),
|
||||
"link_was_copied": MessageLookupByLibrary.simpleMessage(
|
||||
"Ссылка успешно скопирована",
|
||||
),
|
||||
"loading": MessageLookupByLibrary.simpleMessage("Загрузка..."),
|
||||
"mail_was_copied": MessageLookupByLibrary.simpleMessage(
|
||||
"Почта успешно скопирована",
|
||||
),
|
||||
"male": MessageLookupByLibrary.simpleMessage("Мужской"),
|
||||
"meal": MessageLookupByLibrary.simpleMessage("Приём пищи"),
|
||||
"meat": MessageLookupByLibrary.simpleMessage("Мясо"),
|
||||
"meat_type": MessageLookupByLibrary.simpleMessage("С мясом"),
|
||||
"meat_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Диета с мясом полезная и сбалансированная. Включает в себя нежирное мясо: курицу, индейку, кролика или говядину. В сочетании с овощами получаете все необходимые витамины и минералы. Не забывайте о порциях и старайтесь есть медленно, прислушиваясь к своему организму.",
|
||||
),
|
||||
"milliliter": MessageLookupByLibrary.simpleMessage("мл"),
|
||||
"minimal_customer_price": MessageLookupByLibrary.simpleMessage(
|
||||
"Минимальная цена для покупателя: 1200₽",
|
||||
),
|
||||
"most_new": MessageLookupByLibrary.simpleMessage("Самые новые"),
|
||||
"most_old": MessageLookupByLibrary.simpleMessage("Самые старые"),
|
||||
"msg_network_err": MessageLookupByLibrary.simpleMessage("Сетевая ошибка!"),
|
||||
"msg_something_went_wrong": MessageLookupByLibrary.simpleMessage(
|
||||
"Что то пошло не так!",
|
||||
),
|
||||
"my_blog": MessageLookupByLibrary.simpleMessage("Мой блог"),
|
||||
"my_diets": MessageLookupByLibrary.simpleMessage("Мои диеты"),
|
||||
"my_plans": MessageLookupByLibrary.simpleMessage("Мои планы"),
|
||||
"my_settings": MessageLookupByLibrary.simpleMessage("Мои настройки"),
|
||||
"name_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Имя пользователя обязательно для заполнения",
|
||||
),
|
||||
"name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В имени пользователя должно быть минимум 6 символов",
|
||||
),
|
||||
"no": MessageLookupByLibrary.simpleMessage("Нет"),
|
||||
"no_account": MessageLookupByLibrary.simpleMessage("У меня нет аккаунта"),
|
||||
"notifications": MessageLookupByLibrary.simpleMessage("Уведомления"),
|
||||
"one_option": MessageLookupByLibrary.simpleMessage("1 опция"),
|
||||
"option": MessageLookupByLibrary.simpleMessage("Опция"),
|
||||
"option_content": MessageLookupByLibrary.simpleMessage("Содержание опции"),
|
||||
"option_content_hint_text": MessageLookupByLibrary.simpleMessage(
|
||||
"На связи 7 дней в неделю",
|
||||
),
|
||||
"option_desc": MessageLookupByLibrary.simpleMessage("Описание опции"),
|
||||
"option_desc_hint_text": MessageLookupByLibrary.simpleMessage(
|
||||
"Этот план питания для похудения на 7 дней сбалансированный и разнообразный",
|
||||
),
|
||||
"option_duration": MessageLookupByLibrary.simpleMessage(
|
||||
"Продолжительность опции",
|
||||
),
|
||||
"option_personal_diet_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Опция подразумевает создание индивидуальной диеты",
|
||||
),
|
||||
"option_title": MessageLookupByLibrary.simpleMessage("Заголовок опции"),
|
||||
"order": MessageLookupByLibrary.simpleMessage("Порядок"),
|
||||
"password": MessageLookupByLibrary.simpleMessage("Пароль"),
|
||||
"password_confirmation": MessageLookupByLibrary.simpleMessage(
|
||||
"Подтвердите пароль",
|
||||
),
|
||||
"password_confirmation_mismatch": MessageLookupByLibrary.simpleMessage(
|
||||
"Пароли не совпадают",
|
||||
),
|
||||
"password_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Пароль обязателен для заполнения",
|
||||
),
|
||||
"password_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В пароле должно быть минимум 6 символов",
|
||||
),
|
||||
"pcs": MessageLookupByLibrary.simpleMessage("шт"),
|
||||
"personal": MessageLookupByLibrary.simpleMessage("Персональные"),
|
||||
"personal_diet_state": MessageLookupByLibrary.simpleMessage("Персональная"),
|
||||
"photo": MessageLookupByLibrary.simpleMessage("Фото"),
|
||||
"place_of_living": MessageLookupByLibrary.simpleMessage("Место проживания"),
|
||||
"plan_author": MessageLookupByLibrary.simpleMessage("Автор плана"),
|
||||
"plan_desc": MessageLookupByLibrary.simpleMessage("Описание плана"),
|
||||
"plan_desc_example": MessageLookupByLibrary.simpleMessage(
|
||||
"Большое подробное, привлекательное описание плана",
|
||||
),
|
||||
"plan_duration": MessageLookupByLibrary.simpleMessage("Срок плана"),
|
||||
"plan_label_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"План для поддержания формы",
|
||||
),
|
||||
"plans_complete": MessageLookupByLibrary.simpleMessage("Пройденные планы"),
|
||||
"popular": MessageLookupByLibrary.simpleMessage("Популярные"),
|
||||
"preferred_language": MessageLookupByLibrary.simpleMessage(
|
||||
"Предпочитаемый язык общения",
|
||||
),
|
||||
"pressure_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Все показатели давления обязательны к заполнению",
|
||||
),
|
||||
"pressure_is_not_a_number": MessageLookupByLibrary.simpleMessage(
|
||||
"Все показатели давления должны быть числами",
|
||||
),
|
||||
"preview": MessageLookupByLibrary.simpleMessage("Превью"),
|
||||
"price": MessageLookupByLibrary.simpleMessage("Цена"),
|
||||
"price_explanation": MessageLookupByLibrary.simpleMessage(
|
||||
"Разница в ценах, это комиссия Итвио",
|
||||
),
|
||||
"profile": MessageLookupByLibrary.simpleMessage("Профиль"),
|
||||
"proteins": MessageLookupByLibrary.simpleMessage("Белки"),
|
||||
"public_diet_state": MessageLookupByLibrary.simpleMessage("Публичная"),
|
||||
"publish": MessageLookupByLibrary.simpleMessage("Опубликовать"),
|
||||
"published": MessageLookupByLibrary.simpleMessage("Опубликованные"),
|
||||
"removeFromActive": MessageLookupByLibrary.simpleMessage(
|
||||
"Снять с публикации",
|
||||
),
|
||||
"save": MessageLookupByLibrary.simpleMessage("Сохранить"),
|
||||
"services": MessageLookupByLibrary.simpleMessage("Оказание услуг"),
|
||||
"settings": MessageLookupByLibrary.simpleMessage("Настройки"),
|
||||
"share": MessageLookupByLibrary.simpleMessage("Поделиться"),
|
||||
"skip": MessageLookupByLibrary.simpleMessage("Пропустить"),
|
||||
"slim": MessageLookupByLibrary.simpleMessage("Похудение"),
|
||||
"slim_type": MessageLookupByLibrary.simpleMessage("Похудение"),
|
||||
"slim_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"План питания для похудения должен быть разработан с учётом индивидуальных особенностей организма, возраста, пола, уровня физической активности и состояния здоровья. Общие принципы: \n● Снижение калорийности; \n● Сбалансированный рацион; \n● Разнообразие продуктов; \n● Питьевой режим; \n● Ограничение вредных продуктов;",
|
||||
),
|
||||
"standard": MessageLookupByLibrary.simpleMessage("Стандарт"),
|
||||
"startDiet": MessageLookupByLibrary.simpleMessage("Начать диету"),
|
||||
"tell_your_schedule": MessageLookupByLibrary.simpleMessage(
|
||||
"Расскажите в свободной форме о том как просыпаетесь, когда едите, когда ложитесь спать:",
|
||||
),
|
||||
"text_was_copied": MessageLookupByLibrary.simpleMessage(
|
||||
"Текст успешно скопирован",
|
||||
),
|
||||
"three_options": MessageLookupByLibrary.simpleMessage("3 опции"),
|
||||
"toOffer": MessageLookupByLibrary.simpleMessage("Предложить"),
|
||||
"to_draft": MessageLookupByLibrary.simpleMessage("В черновик"),
|
||||
"unfavorite_foods": MessageLookupByLibrary.simpleMessage(
|
||||
"Нелюбимые продукты",
|
||||
),
|
||||
"up_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
"Верхние показатели давления:",
|
||||
),
|
||||
"user_authorization": MessageLookupByLibrary.simpleMessage(
|
||||
"Аутентификация",
|
||||
),
|
||||
"user_data": MessageLookupByLibrary.simpleMessage("Данные пользователя"),
|
||||
"user_registration": MessageLookupByLibrary.simpleMessage(
|
||||
"Регистрация пользователя",
|
||||
),
|
||||
"username": MessageLookupByLibrary.simpleMessage("Имя пользователя"),
|
||||
"vegan": MessageLookupByLibrary.simpleMessage("Веган."),
|
||||
"vegan_type": MessageLookupByLibrary.simpleMessage("Вегетарианская"),
|
||||
"vegan_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Диета основана на потреблении растительной пищи и отказе от продуктов животного происхождения. Такой тип питания может быть разнообразным и вкусным, а также полезным для здоровья.",
|
||||
),
|
||||
"waist": MessageLookupByLibrary.simpleMessage("Талия"),
|
||||
"waist_circumference": MessageLookupByLibrary.simpleMessage("Обхват талии"),
|
||||
"weight": MessageLookupByLibrary.simpleMessage("Вес"),
|
||||
"weight_chart": MessageLookupByLibrary.simpleMessage("График веса"),
|
||||
"weight_measurements": MessageLookupByLibrary.simpleMessage("Замер веса"),
|
||||
"wellness": MessageLookupByLibrary.simpleMessage("Улучшение самочувствия"),
|
||||
"wellness_type": MessageLookupByLibrary.simpleMessage(
|
||||
"Улучшение самочувствия",
|
||||
),
|
||||
"wellness_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы.",
|
||||
),
|
||||
"what_is_your_name": MessageLookupByLibrary.simpleMessage("Как вас зовут?"),
|
||||
"wrong_credentials": MessageLookupByLibrary.simpleMessage(
|
||||
"Неверные данные пользователя",
|
||||
),
|
||||
"you_will_get": MessageLookupByLibrary.simpleMessage("Вы получите"),
|
||||
"your_blood_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
"Ваше артериальное давление?",
|
||||
),
|
||||
"your_favorite_sports": MessageLookupByLibrary.simpleMessage(
|
||||
"Ваши спортивные увлечения?",
|
||||
),
|
||||
"your_gender": MessageLookupByLibrary.simpleMessage("Ваш пол?"),
|
||||
"your_height": MessageLookupByLibrary.simpleMessage("Ваш рост:"),
|
||||
"your_schedule": MessageLookupByLibrary.simpleMessage("Ваш режим дня?"),
|
||||
"your_weight": MessageLookupByLibrary.simpleMessage("Ваш вес:"),
|
||||
static _notInlinedMessages(_) => <String, Function> {
|
||||
"Moscow" : MessageLookupByLibrary.simpleMessage("Москва"),
|
||||
"Russia" : MessageLookupByLibrary.simpleMessage("Россия"),
|
||||
"about_diet" : MessageLookupByLibrary.simpleMessage("Об этой диете"),
|
||||
"about_plan" : MessageLookupByLibrary.simpleMessage("Об этом плане"),
|
||||
"active" : MessageLookupByLibrary.simpleMessage("Активен"),
|
||||
"active_diet_state" : MessageLookupByLibrary.simpleMessage("Активная"),
|
||||
"add" : MessageLookupByLibrary.simpleMessage("Добавить"),
|
||||
"add_cover" : MessageLookupByLibrary.simpleMessage("Добавьте обложку"),
|
||||
"add_measure" : MessageLookupByLibrary.simpleMessage("Добавить замер"),
|
||||
"adding_plan" : MessageLookupByLibrary.simpleMessage("Добавление плана"),
|
||||
"additional_information" : MessageLookupByLibrary.simpleMessage("Дополнительная информация"),
|
||||
"admin" : MessageLookupByLibrary.simpleMessage("Админ"),
|
||||
"all" : MessageLookupByLibrary.simpleMessage("Все"),
|
||||
"allergies_presence" : MessageLookupByLibrary.simpleMessage("Наличие аллергии"),
|
||||
"another_form_of_comment" : MessageLookupByLibrary.simpleMessage("комментария"),
|
||||
"another_form_of_day" : MessageLookupByLibrary.simpleMessage("дня"),
|
||||
"answer" : MessageLookupByLibrary.simpleMessage("Ответить"),
|
||||
"archived" : MessageLookupByLibrary.simpleMessage("В архиве"),
|
||||
"authentificate" : MessageLookupByLibrary.simpleMessage("Войти"),
|
||||
"average_pressure" : MessageLookupByLibrary.simpleMessage("Средние показатели давления:"),
|
||||
"bodymass_chart" : MessageLookupByLibrary.simpleMessage("График ИМТ"),
|
||||
"by_default" : MessageLookupByLibrary.simpleMessage("По умолчанию"),
|
||||
"calories" : MessageLookupByLibrary.simpleMessage("Калории"),
|
||||
"carb_type" : MessageLookupByLibrary.simpleMessage("Мучное"),
|
||||
"carb_type_desc" : MessageLookupByLibrary.simpleMessage("Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы."),
|
||||
"carbohydrates" : MessageLookupByLibrary.simpleMessage("Углеводы"),
|
||||
"chat" : MessageLookupByLibrary.simpleMessage("Чат"),
|
||||
"chest" : MessageLookupByLibrary.simpleMessage("Грудь"),
|
||||
"chest_circumference" : MessageLookupByLibrary.simpleMessage("Обхват груди"),
|
||||
"choose_diet_duration" : MessageLookupByLibrary.simpleMessage("Выберите срок диеты"),
|
||||
"choose_plan_duration" : MessageLookupByLibrary.simpleMessage("Выберите срок плана"),
|
||||
"choose_start_diet_date" : MessageLookupByLibrary.simpleMessage("Выберите дату старты диеты. Она отобразиться у Вас в дневнике"),
|
||||
"circumference_empty" : MessageLookupByLibrary.simpleMessage("Все замеры обязательны к заполнению"),
|
||||
"circumference_is_not_a_number" : MessageLookupByLibrary.simpleMessage("Все замеры должны быть числами"),
|
||||
"circumferences_chart" : MessageLookupByLibrary.simpleMessage("График обхватов"),
|
||||
"city" : MessageLookupByLibrary.simpleMessage("Город"),
|
||||
"city_of_living" : MessageLookupByLibrary.simpleMessage("Город проживания"),
|
||||
"comfort" : MessageLookupByLibrary.simpleMessage("Комфорт"),
|
||||
"comment" : MessageLookupByLibrary.simpleMessage("комментарий"),
|
||||
"comment_hint" : MessageLookupByLibrary.simpleMessage("Комментарий"),
|
||||
"comments" : MessageLookupByLibrary.simpleMessage("Комментарии"),
|
||||
"comments_plural" : MessageLookupByLibrary.simpleMessage("комментариев"),
|
||||
"complain" : MessageLookupByLibrary.simpleMessage("Пожаловаться"),
|
||||
"continueButton" : MessageLookupByLibrary.simpleMessage("Продолжить"),
|
||||
"continue_" : MessageLookupByLibrary.simpleMessage("Продолжить"),
|
||||
"copied" : MessageLookupByLibrary.simpleMessage("cкопирован"),
|
||||
"copy_link" : MessageLookupByLibrary.simpleMessage("Скопировать ссылку"),
|
||||
"country" : MessageLookupByLibrary.simpleMessage("Страна"),
|
||||
"create_diet" : MessageLookupByLibrary.simpleMessage("Создание диеты"),
|
||||
"customer_price" : MessageLookupByLibrary.simpleMessage("Цена для покупателя"),
|
||||
"date_of_birth" : MessageLookupByLibrary.simpleMessage("Дата рождения"),
|
||||
"day" : MessageLookupByLibrary.simpleMessage("День"),
|
||||
"days" : MessageLookupByLibrary.simpleMessage("дней"),
|
||||
"deleted" : MessageLookupByLibrary.simpleMessage("Удалена"),
|
||||
"diary" : MessageLookupByLibrary.simpleMessage("Дневник"),
|
||||
"diet" : MessageLookupByLibrary.simpleMessage("Диета"),
|
||||
"diet_author" : MessageLookupByLibrary.simpleMessage("Автор диеты"),
|
||||
"diet_plan" : MessageLookupByLibrary.simpleMessage("План диеты"),
|
||||
"diet_state" : MessageLookupByLibrary.simpleMessage("Статус диеты"),
|
||||
"diet_type" : MessageLookupByLibrary.simpleMessage("Тип диеты"),
|
||||
"do_you_have_hypertension_tendency" : MessageLookupByLibrary.simpleMessage("Есть ли у вас гипертония?"),
|
||||
"do_you_have_hypotension_tendency" : MessageLookupByLibrary.simpleMessage("Есть ли у вас гипотония?"),
|
||||
"do_you_take_pills" : MessageLookupByLibrary.simpleMessage("Принимаете ли вы лекарства или бады?"),
|
||||
"down_pressure" : MessageLookupByLibrary.simpleMessage("Нижние показатели давления:"),
|
||||
"draft" : MessageLookupByLibrary.simpleMessage("Черновик"),
|
||||
"drafted" : MessageLookupByLibrary.simpleMessage("Черновики"),
|
||||
"eating_behavior" : MessageLookupByLibrary.simpleMessage("Пищевое поведение"),
|
||||
"eating_behavior_type" : MessageLookupByLibrary.simpleMessage("Формирование пищевого поведения"),
|
||||
"eating_behavior_type_desc" : MessageLookupByLibrary.simpleMessage("Формирование здорового пищевого поведения — это процесс, который включает в себя изменение привычек и отношения к еде. Он направлен на то, чтобы помочь людям научиться правильно питаться и поддерживать здоровый образ жизни.Основные принципы формирования здорового пищевого поведения: \n● Разнообразие продуктов; \n● Сбалансированный рацион; \n● Питьевой режим; \n● Ограничение вредных продуктов; \n● Регулярные приёмы пищи; \n● Умеренность;Осознанное питание; \n● Физическая активность;"),
|
||||
"economy" : MessageLookupByLibrary.simpleMessage("Эконом"),
|
||||
"edit" : MessageLookupByLibrary.simpleMessage("Редактировать"),
|
||||
"email" : MessageLookupByLibrary.simpleMessage("Электронная почта"),
|
||||
"email_empty" : MessageLookupByLibrary.simpleMessage("Необходимо ввести адрес электронной почты"),
|
||||
"email_invalid" : MessageLookupByLibrary.simpleMessage("Некорректный адрес электронной почты"),
|
||||
"enter_additional_information" : MessageLookupByLibrary.simpleMessage("Введите любую дополнительную информацию на своё усмотрение:"),
|
||||
"enter_diet_description" : MessageLookupByLibrary.simpleMessage("Введите описание диеты"),
|
||||
"enter_diet_name" : MessageLookupByLibrary.simpleMessage("Выведите название диеты"),
|
||||
"enter_information" : MessageLookupByLibrary.simpleMessage("Введите информацию..."),
|
||||
"exit" : MessageLookupByLibrary.simpleMessage("Выйти"),
|
||||
"expand" : MessageLookupByLibrary.simpleMessage("Показать полностью"),
|
||||
"fats" : MessageLookupByLibrary.simpleMessage("Жиры"),
|
||||
"favorite_foods" : MessageLookupByLibrary.simpleMessage("Любимые продукты"),
|
||||
"favorite_unfavorite_foods" : MessageLookupByLibrary.simpleMessage("Ваши любимые/нелюбимые продукты питания?"),
|
||||
"female" : MessageLookupByLibrary.simpleMessage("Женский"),
|
||||
"fill_in_information" : MessageLookupByLibrary.simpleMessage("Заполните информацию:"),
|
||||
"finish" : MessageLookupByLibrary.simpleMessage("Завершить"),
|
||||
"first_name" : MessageLookupByLibrary.simpleMessage("Имя"),
|
||||
"first_name_empty" : MessageLookupByLibrary.simpleMessage("Имя обязательно для заполнения"),
|
||||
"first_name_short" : MessageLookupByLibrary.simpleMessage("В имени должен быть минимум 1 символ"),
|
||||
"fit_type" : MessageLookupByLibrary.simpleMessage("Поддержание формы"),
|
||||
"fit_type_desc" : MessageLookupByLibrary.simpleMessage("План питания для поддержания формы сбалансированный и разнообразный, чтобы обеспечить организм всеми необходимыми питательными веществами. Общие принципы: \n● Дробное питание; \n● Разнообразие продуктов; \n● Контроль порций; \n● Питьевой режим; \n● Ограничение вредных продуктов;"),
|
||||
"fitness" : MessageLookupByLibrary.simpleMessage("Поддержка формы"),
|
||||
"from" : MessageLookupByLibrary.simpleMessage("от"),
|
||||
"from_a_to_z" : MessageLookupByLibrary.simpleMessage("Название: А-Я"),
|
||||
"from_z_to_a" : MessageLookupByLibrary.simpleMessage("Название: Я-А"),
|
||||
"gallery" : MessageLookupByLibrary.simpleMessage("Галерея"),
|
||||
"gr" : MessageLookupByLibrary.simpleMessage("гр"),
|
||||
"grams" : MessageLookupByLibrary.simpleMessage("гр"),
|
||||
"height_measurements" : MessageLookupByLibrary.simpleMessage("Замер роста"),
|
||||
"hide" : MessageLookupByLibrary.simpleMessage("Свернуть"),
|
||||
"hip_circumference" : MessageLookupByLibrary.simpleMessage("Обхват бедер"),
|
||||
"hips" : MessageLookupByLibrary.simpleMessage("Бедра"),
|
||||
"in_progress" : MessageLookupByLibrary.simpleMessage("В процессе"),
|
||||
"inactive_diet_state" : MessageLookupByLibrary.simpleMessage("Черновик"),
|
||||
"infoAboutOrder" : MessageLookupByLibrary.simpleMessage("Информация о заказе"),
|
||||
"initial_measurements" : MessageLookupByLibrary.simpleMessage("Первичные замеры"),
|
||||
"label" : MessageLookupByLibrary.simpleMessage("Название"),
|
||||
"language" : MessageLookupByLibrary.simpleMessage("Язык"),
|
||||
"last_name" : MessageLookupByLibrary.simpleMessage("Фамилия"),
|
||||
"last_name_empty" : MessageLookupByLibrary.simpleMessage("Фамилия обязательна для заполнения"),
|
||||
"last_name_short" : MessageLookupByLibrary.simpleMessage("В фамилии должен быть минимум 6 символов"),
|
||||
"lbl_english" : MessageLookupByLibrary.simpleMessage("English"),
|
||||
"light_type" : MessageLookupByLibrary.simpleMessage("Легкая"),
|
||||
"light_type_desc" : MessageLookupByLibrary.simpleMessage("С некоторыми видами диет можно употреблять алкоголь в умеренных количествах. Рекомендуется совмещать вместе с низкокалорийными закусками."),
|
||||
"link_was_copied" : MessageLookupByLibrary.simpleMessage("Ссылка успешно скопирована"),
|
||||
"loading" : MessageLookupByLibrary.simpleMessage("Загрузка..."),
|
||||
"mail_was_copied" : MessageLookupByLibrary.simpleMessage("Почта успешно скопирована"),
|
||||
"male" : MessageLookupByLibrary.simpleMessage("Мужской"),
|
||||
"meal" : MessageLookupByLibrary.simpleMessage("Приём пищи"),
|
||||
"meat" : MessageLookupByLibrary.simpleMessage("Мясо"),
|
||||
"meat_type" : MessageLookupByLibrary.simpleMessage("С мясом"),
|
||||
"meat_type_desc" : MessageLookupByLibrary.simpleMessage("Диета с мясом полезная и сбалансированная. Включает в себя нежирное мясо: курицу, индейку, кролика или говядину. В сочетании с овощами получаете все необходимые витамины и минералы. Не забывайте о порциях и старайтесь есть медленно, прислушиваясь к своему организму."),
|
||||
"milliliter" : MessageLookupByLibrary.simpleMessage("мл"),
|
||||
"minimal_customer_price" : MessageLookupByLibrary.simpleMessage("Минимальная цена для покупателя: 1200₽"),
|
||||
"most_new" : MessageLookupByLibrary.simpleMessage("Самые новые"),
|
||||
"most_old" : MessageLookupByLibrary.simpleMessage("Самые старые"),
|
||||
"msg_network_err" : MessageLookupByLibrary.simpleMessage("Сетевая ошибка!"),
|
||||
"msg_something_went_wrong" : MessageLookupByLibrary.simpleMessage("Что то пошло не так!"),
|
||||
"my_blog" : MessageLookupByLibrary.simpleMessage("Мой блог"),
|
||||
"my_diets" : MessageLookupByLibrary.simpleMessage("Мои диеты"),
|
||||
"my_plans" : MessageLookupByLibrary.simpleMessage("Мои планы"),
|
||||
"my_settings" : MessageLookupByLibrary.simpleMessage("Мои настройки"),
|
||||
"name_empty" : MessageLookupByLibrary.simpleMessage("Имя пользователя обязательно для заполнения"),
|
||||
"name_short" : MessageLookupByLibrary.simpleMessage("В имени пользователя должно быть минимум 6 символов"),
|
||||
"no" : MessageLookupByLibrary.simpleMessage("Нет"),
|
||||
"no_account" : MessageLookupByLibrary.simpleMessage("У меня нет аккаунта"),
|
||||
"notifications" : MessageLookupByLibrary.simpleMessage("Уведомления"),
|
||||
"one_option" : MessageLookupByLibrary.simpleMessage("1 опция"),
|
||||
"option" : MessageLookupByLibrary.simpleMessage("Опция"),
|
||||
"option_content" : MessageLookupByLibrary.simpleMessage("Содержание опции"),
|
||||
"option_content_hint_text" : MessageLookupByLibrary.simpleMessage("На связи 7 дней в неделю"),
|
||||
"option_desc" : MessageLookupByLibrary.simpleMessage("Описание опции"),
|
||||
"option_desc_hint_text" : MessageLookupByLibrary.simpleMessage("Этот план питания для похудения на 7 дней сбалансированный и разнообразный"),
|
||||
"option_duration" : MessageLookupByLibrary.simpleMessage("Продолжительность опции"),
|
||||
"option_personal_diet_desc" : MessageLookupByLibrary.simpleMessage("Опция подразумевает создание индивидуальной диеты"),
|
||||
"option_title" : MessageLookupByLibrary.simpleMessage("Заголовок опции"),
|
||||
"order" : MessageLookupByLibrary.simpleMessage("Порядок"),
|
||||
"password" : MessageLookupByLibrary.simpleMessage("Пароль"),
|
||||
"password_confirmation" : MessageLookupByLibrary.simpleMessage("Подтвердите пароль"),
|
||||
"password_confirmation_mismatch" : MessageLookupByLibrary.simpleMessage("Пароли не совпадают"),
|
||||
"password_empty" : MessageLookupByLibrary.simpleMessage("Пароль обязателен для заполнения"),
|
||||
"password_short" : MessageLookupByLibrary.simpleMessage("В пароле должно быть минимум 6 символов"),
|
||||
"pcs" : MessageLookupByLibrary.simpleMessage("шт"),
|
||||
"personal" : MessageLookupByLibrary.simpleMessage("Персональные"),
|
||||
"personal_diet_state" : MessageLookupByLibrary.simpleMessage("Персональная"),
|
||||
"photo" : MessageLookupByLibrary.simpleMessage("Фото"),
|
||||
"place_of_living" : MessageLookupByLibrary.simpleMessage("Место проживания"),
|
||||
"plan_author" : MessageLookupByLibrary.simpleMessage("Автор плана"),
|
||||
"plan_desc" : MessageLookupByLibrary.simpleMessage("Описание плана"),
|
||||
"plan_desc_example" : MessageLookupByLibrary.simpleMessage("Большое подробное, привлекательное описание плана"),
|
||||
"plan_duration" : MessageLookupByLibrary.simpleMessage("Срок плана"),
|
||||
"plan_label_desc" : MessageLookupByLibrary.simpleMessage("План для поддержания формы"),
|
||||
"plans_complete" : MessageLookupByLibrary.simpleMessage("Пройденные планы"),
|
||||
"popular" : MessageLookupByLibrary.simpleMessage("Популярные"),
|
||||
"preferred_language" : MessageLookupByLibrary.simpleMessage("Предпочитаемый язык общения"),
|
||||
"pressure_empty" : MessageLookupByLibrary.simpleMessage("Все показатели давления обязательны к заполнению"),
|
||||
"pressure_is_not_a_number" : MessageLookupByLibrary.simpleMessage("Все показатели давления должны быть числами"),
|
||||
"preview" : MessageLookupByLibrary.simpleMessage("Превью"),
|
||||
"price" : MessageLookupByLibrary.simpleMessage("Цена"),
|
||||
"price_explanation" : MessageLookupByLibrary.simpleMessage("Разница в ценах, это комиссия Итвио"),
|
||||
"profile" : MessageLookupByLibrary.simpleMessage("Профиль"),
|
||||
"proteins" : MessageLookupByLibrary.simpleMessage("Белки"),
|
||||
"public_diet_state" : MessageLookupByLibrary.simpleMessage("Публичная"),
|
||||
"publish" : MessageLookupByLibrary.simpleMessage("Опубликовать"),
|
||||
"published" : MessageLookupByLibrary.simpleMessage("Опубликованные"),
|
||||
"removeFromActive" : MessageLookupByLibrary.simpleMessage("Снять с публикации"),
|
||||
"save" : MessageLookupByLibrary.simpleMessage("Сохранить"),
|
||||
"services" : MessageLookupByLibrary.simpleMessage("Оказание услуг"),
|
||||
"settings" : MessageLookupByLibrary.simpleMessage("Настройки"),
|
||||
"share" : MessageLookupByLibrary.simpleMessage("Поделиться"),
|
||||
"skip" : MessageLookupByLibrary.simpleMessage("Пропустить"),
|
||||
"slim" : MessageLookupByLibrary.simpleMessage("Похудение"),
|
||||
"slim_type" : MessageLookupByLibrary.simpleMessage("Похудение"),
|
||||
"slim_type_desc" : MessageLookupByLibrary.simpleMessage("План питания для похудения должен быть разработан с учётом индивидуальных особенностей организма, возраста, пола, уровня физической активности и состояния здоровья. Общие принципы: \n● Снижение калорийности; \n● Сбалансированный рацион; \n● Разнообразие продуктов; \n● Питьевой режим; \n● Ограничение вредных продуктов;"),
|
||||
"standard" : MessageLookupByLibrary.simpleMessage("Стандарт"),
|
||||
"startDiet" : MessageLookupByLibrary.simpleMessage("Начать диету"),
|
||||
"tell_your_schedule" : MessageLookupByLibrary.simpleMessage("Расскажите в свободной форме о том как просыпаетесь, когда едите, когда ложитесь спать:"),
|
||||
"text_was_copied" : MessageLookupByLibrary.simpleMessage("Текст успешно скопирован"),
|
||||
"three_options" : MessageLookupByLibrary.simpleMessage("3 опции"),
|
||||
"toOffer" : MessageLookupByLibrary.simpleMessage("Предложить"),
|
||||
"to_draft" : MessageLookupByLibrary.simpleMessage("В черновик"),
|
||||
"unfavorite_foods" : MessageLookupByLibrary.simpleMessage("Нелюбимые продукты"),
|
||||
"up_pressure" : MessageLookupByLibrary.simpleMessage("Верхние показатели давления:"),
|
||||
"user_authorization" : MessageLookupByLibrary.simpleMessage("Аутентификация"),
|
||||
"user_data" : MessageLookupByLibrary.simpleMessage("Данные пользователя"),
|
||||
"user_registration" : MessageLookupByLibrary.simpleMessage("Регистрация пользователя"),
|
||||
"username" : MessageLookupByLibrary.simpleMessage("Имя пользователя"),
|
||||
"vegan" : MessageLookupByLibrary.simpleMessage("Веган."),
|
||||
"vegan_type" : MessageLookupByLibrary.simpleMessage("Вегетарианская"),
|
||||
"vegan_type_desc" : MessageLookupByLibrary.simpleMessage("Диета основана на потреблении растительной пищи и отказе от продуктов животного происхождения. Такой тип питания может быть разнообразным и вкусным, а также полезным для здоровья."),
|
||||
"waist" : MessageLookupByLibrary.simpleMessage("Талия"),
|
||||
"waist_circumference" : MessageLookupByLibrary.simpleMessage("Обхват талии"),
|
||||
"weight" : MessageLookupByLibrary.simpleMessage("Вес"),
|
||||
"weight_chart" : MessageLookupByLibrary.simpleMessage("График веса"),
|
||||
"weight_measurements" : MessageLookupByLibrary.simpleMessage("Замер веса"),
|
||||
"wellness" : MessageLookupByLibrary.simpleMessage("Улучшение самочувствия"),
|
||||
"wellness_type" : MessageLookupByLibrary.simpleMessage("Улучшение самочувствия"),
|
||||
"wellness_type_desc" : MessageLookupByLibrary.simpleMessage("Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы."),
|
||||
"what_is_your_name" : MessageLookupByLibrary.simpleMessage("Как вас зовут?"),
|
||||
"wrong_credentials" : MessageLookupByLibrary.simpleMessage("Неверные данные пользователя"),
|
||||
"you_will_get" : MessageLookupByLibrary.simpleMessage("Вы получите"),
|
||||
"your_blood_pressure" : MessageLookupByLibrary.simpleMessage("Ваше артериальное давление?"),
|
||||
"your_favorite_sports" : MessageLookupByLibrary.simpleMessage("Ваши спортивные увлечения?"),
|
||||
"your_gender" : MessageLookupByLibrary.simpleMessage("Ваш пол?"),
|
||||
"your_height" : MessageLookupByLibrary.simpleMessage("Ваш рост:"),
|
||||
"your_schedule" : MessageLookupByLibrary.simpleMessage("Ваш режим дня?"),
|
||||
"your_weight" : MessageLookupByLibrary.simpleMessage("Ваш вес:")
|
||||
};
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -466,6 +466,7 @@
|
||||
"weAreLookingFor": "Мы собираем самое большое сообщество людей, желающих вести здоровый образ жизни!",
|
||||
"letsInvite": "Давайте пригласим близких в итвио",
|
||||
"eatvioIsAHelthyHabbit": "Итвио — это полезная привычка",
|
||||
"invite": "Пригласить"
|
||||
"invite": "Пригласить",
|
||||
"comment_hint": "Комментарий"
|
||||
}
|
||||
|
||||
|
||||
@@ -215,5 +215,6 @@
|
||||
"from": "от",
|
||||
"user_data": "Данные пользователя",
|
||||
"infoAboutOrder": "Информация о заказе",
|
||||
"notifications": "Уведомления"
|
||||
"notifications": "Уведомления",
|
||||
"comment_hint": "Комментарий"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user