В этом руководстве мы собираемся взять вас через процесс доступов вашего приложения и удобно для людей по всему миру. Только около 20 процентов мира говорят на английском языке, поэтому предоставление другим языковым вариантам может улучшить ваш пользовательский опыт и значительно повысить досягаемость вашего приложения. Мы собираемся взглянуть на встроенную интернационализацию Angular и показать вам, как их правильно использовать.
Если вы строите сайт, а не приложение, будьте уверены, что вы получили ваш набор инструментов. Увидеть наши руководства в лучшем Строитель сайта и топ веб хостинг узнать больше.
Мы создали очень простое демонстрационное приложение для демонстрации процесса. Клонировать это отсюда а затем следуйте инструкциям по установке.
Начните приложение, чтобы ознакомиться с ним. Это просто отображает и обновляет случайные номера и значения с разными контекстами, например, Валюты, даты и т. Д. Мы покроем некоторые трубы и функции, используемые во время учебника.
Существует два слова, которые часто используются взаимозаменяемо, когда говорят о переводе приложений - интернационализации и локализации - однако они на самом деле значат немного разных вещей. Интернационализация относится к процессу подготовки вашего приложения для поддержки различных языков. Напротив, локализация относится к процессу фактического перевода вашего приложения на ваши необходимые языки. По сути, интернационализация - это то, что вы делаете один раз за приложение, и локализация происходит один раз за локаль - по крайней мере, это план.
Эти термины могут также быть знакомы в их сокращенных версиях: i18n (где 18 - количество букв между первым «I» и последним «n» интернационализации) и L10N (где 10 - количество букв между «I» и «n» локализации).
Сегодня во всем мире используются более 6000 языков, большинство из которых используются только очень небольшими группами людей. Тем не менее, даже если мы сосредоточимся только на трех лучших языках - мандарин, испанском и английском языках - будут существенные различия в форматировании даты, грамматической структурой, плюрализы и форматирования числа.
Если мы включаем пятый наиболее широко используемый язык - арабский - мы столкнулись с другой разницей; Арабский - это скрипт влево (RTL), который означает, что пользовательский интерфейс также должен быть зеркальным.
Таким образом, во время локализации мы должны рассмотреть грамматику, различия на макете и форматировании, и, конечно, мы также должны изменить сам текст. Угловой может помочь с большим количеством этого, но вам все равно нужно вручную перевести текст (и сохранить перевод в облачное хранилище Так что это безопасно и совпадает с вашей командой).
Нам нужно будет локализовать для каждого языка, нам нужно поддерживать. Месторождение относится к общему набору предпочтений для соображений, упомянутых выше, которые имеют тенденцию участвовать в регионе мира, как правило, страна. Каждая локаль представлена идентификатором локали Unicode, который указывает код языка и расширение локали.
Локаль по умолчанию Угловой по умолчанию «EN-US», который является языковым кодом 'EN' (английский), как говорят в регионе «США» (Соединенные Штаты Америки). Приложение, локализованное для «ru-us», будет тонко отличаться от локализованного приложения для «en-gb», который является английским языком, как говорится в Великобритании. Например, в датах США (отбиение) отформатированы мм / дд / ггг, тогда как здесь в Великобритании мы используем более разумный подход DD / MM / Yyyy. Это незначительное различие может привести к серьезной ошибке в понимании.
Чтобы сделать вещи интересными, давайте локализовать наше демонстрационное приложение для арабского языка, как говорят в Ираке, ака «AR-IQ» и английский, как говорят в Великобритании, ака «EN-GB». Мы будем использовать английский как по умолчанию на этот раз.
Наш демонстрационный проект был создан с использованием угловых CLI, который включает в себя некоторые полезные инструменты. Мы собираемся использовать предпортирующие (AOT) компилятор для этого проекта, поэтому нам нужно внести некоторые изменения в файл конфигурации CLI: «Angular.json». Если вы хотите использовать просто вовремя (JIT), вам нужно настроить вещи немного по-разному.
С помощью AOT Build вы получаете небольшой, более быстрый рендеринг-приложение, которое загружается без необходимости асинхронных запросов, чтобы получить такие вещи, как шаблоны и стилы. В результате вы должны создать сборку для каждого языка и обслуживать соответствующую сборку, используя URL или какой-то логику обнаружения языка на стороне сервера. Самый простой подход - создать каталог для каждого языка, например, www.example.com/en-gb и www.example.com/ar-iq. Тренование состоит в том, что вы не можете переключать язык на лету, но вряд ли вряд ли будет что-то, требующее настоящими пользователями.
Прежде всего, нам нужно добавить конфигурацию сборки для нашего арабского языка. В файле JSON ищите объект «Architecty.Build.Configurations». Добавьте следующий блок, чтобы определить конфигурацию для локали:
«AR-IQ»: {
«BASEHREF»: «/ AR-IQ /»,
«Deployerll»: «/ AR-IQ /»,
«OptionPath»: «dist / ingular-i18n-demo /
AR-IQ »,
"I18nfile": "SRC / locale / messages.ar-iq.
xlf ",
«I18NFormat»: «XLF»,
"I18nlocale": "AR-IQ"
Эта конфигурация сообщает Angular, где выводить сборку сборки, а какие переводы файлы и формат в использовании. Он также устанавливает локаль и говорит о том, какой каталог приложение будет развернуто.
Нам также необходимо изменить параметры по умолчанию в «Architection.Build.Options», чтобы использовать локаль «en-gb». Установите следующие свойства, как показано на рисунке. Обратите внимание, что мы включаем AOT здесь через доску, поэтому его будет использоваться для создания продукции и развития:
«OptionPath»: «dist / ingular-i18n-demo /
en-gb ",
"I18nlocale": "en-gb",
"Deployerll": "/ en-gb /",
«BASEHREF»: «/ EN-GB /»,
«AOT»: True
Угловая поддерживает ряд локалей. Убедитесь, что вы используете правильное значение для свойства «I18NLOCALE». Вы можете увидеть полный список здесь Отказ
За кулисами приведенные выше конфигурации просто загружают и прочитайте из одного из этих файлов предпочтений локали.
В дополнение к настройке вывода сборки нам также необходимо настроить конфигурацию для команды «NG Service» для разработки. Это более просто, так как мы можем просто ссылаться на конфигурацию сборки, которую мы только что добавили. В «Angular.json» добавляют следующий блок для «Architection.serve.Configurations»:
«AR-IQ»: {
«Брауссоргет»: «Angular-I18n-
Демо: сборка: AR-IQ ",
«ARMPATH»: «/ AR-IQ /»
}
Здесь мы имеем ссылку на параметры конфигурации сборки, используя свойство «Browsertarget», и мы также устанавливаем «сервис». Прежде чем мы сможем подать или построить арабское приложение, нам нужно создать файл переводов, на которые ссылается на свойство «i18nfile» выше. Angular CLI включает в себя инструмент для извлечения помещенного текста в исходный файл стандартной отрасли.
Подробнее мы осмотрим эти файлы позже в руководстве, но на данный момент нам просто нужно экспортировать базовый пустой файл, чтобы позволить нам компилировать.
Мы будем использовать команду «NG XI18N» со следующими параметрами. Это единственный раз, когда мы включаем идентификатор локали в файле имени пользователя:
$ ng xi18n --output-path locale --out-файл
messages.ar-iq.xlf --i18n-locale AR-IQ
Это должно создать файл в каталоге SRC / Locale. Отныне мы всегда будем выводить файл с именем «messages.xlf» и вручную скопируйте его через версию с идентификатором локали в названии. Причина этого состоит в том, чтобы предотвратить перезапись инструмента извлечения любых существующих переводов, которые мы добавили в файл.
На данный момент мы теперь можем скомпилировать проект и посмотреть, что происходит, но нам нужно сказать команду «NG Service», которая используется для использования. Сначала давайте посмотрим на английскую версию. Нет никаких изменений здесь, потому что английский по умолчанию:
$ NG служить
Как вы можете видеть, это выглядит очень похоже на оригинальную версию, которая использует локаль по умолчанию угловой по умолчанию «RU-US». Заметное разница в том, что валюта теперь указывает US $ вместо всего за $. Хорошо, теперь давайте попробуем арабскую версию. Остановите английскую версию и запустите:
$ NG служат --configuration = AR-IQ
Поскольку вы ожидаете, что в этой версии более очевидные различия, в частности, дата сейчас написана на арабском языке. Угловой может сделать это потому, что имена некоторых вещей, таких как месяцы и дни, из строя, и в конечном итоге они относятся к известному номеру. Все остальное, однако, все еще на английском языке.
Посмотрите на исходный код «app.component.html», и вы увидите, что мы используем количество различных труб. Следующие угловые трубы являются известными локалью, что означает, что они адаптируют их вывод на основе текущей локали: «Дата Деймения», «CurrencyPype», «Декомасляч» и «Процентная задача».
Если вы используете эти трубы, тщательно угловые будут обрабатывать много локализации Legwork для вас. Тщательно мы имеем в виду использование доступных предопределенных вариантов везде, где вы можете. Хорошим примером является форматирование даты США против Великобритании, которое мы упоминали ранее. Если вы находитесь в Великобритании, и вы хотите отобразить дату, используя (разумный) одномесячный формат, вы можете расстроиться, чтобы найти, что предопределенный параметр «Shortdate» отображается как M / D / YY (например, . 09/9/18) И будьте соблазнены жесткокодировать ваш желаемый формат, как это:
{{mydate | Дата: 'dd / mm / y'}}
Но теперь мы знаем, что мы получаем формат M / D / YY, потому что угловые используются локаль «en-As» по умолчанию. Таким образом, вместо того, чтобы жесткодировать формат, мы должны использовать опцию «Shortdate» и локализовать наше приложение для использования «en-gb».
{{mydate | Дата: «Шортдат»}}
Требуется крошечные усилия, но затем мы можем добавить локальные доставки в контент нашего сердца и всегда иметь удобный формат даты.
К сожалению, не кажется, что есть простой, встроенный способ переопределить предопределенный формат. Например, вы не можете просто решить, что вы предпочитаете формат «Shortdate», чтобы быть DD / MM / YYYY вместо DD / мм / y, так как нет способа изменить формат во время выполнения. Также вы не можете добавить свои собственные предопределенные варианты.
Для этих краевых случаев вы можете создать пользовательскую дату трубы, которая обертывает угловую «DatePipe» и обрабатывает любые пользовательские форматы на локаль. Все, что он не признает, будет передан встроенному «DatePipe».
С полки «CurrencyPipe» отформатирует номер в качестве доллара США, обрезать до двух десятичных знаков и добавлять группировки, как определено в предпочтениях локали.
Вы заметите, что на наших медах валюта всегда в долларах США. Он не магически переключается на стерлинг (GBP), когда вы используете локаль «en-GB». Причина этого заключается в том, что £ 10 не совпадает с 10 долларов, поэтому вы должны явно указать валюту, к которому относится ваш номер.
Давайте обновим «app.component.html», чтобы использовать GBP по всему. При указании кода валют необходимо использовать правильное значение из стандарта ISO 4217 (список доступных онлайн).
Измените два валютных труба, добавив «:« GBP », как так:
{{значение $ | async |. Валюта: 'GBP'}}
И вы начнете видеть символ £ вместо US $.
Помните, что не делает ничего умного, как автоматически конвертировать USD в эквивалентное значение в GBP, если вы измените валюту - это просто меняет символ, который он использует.
Итак, у нас есть наши два локаля, настроенные и угловые полезно выполняют некоторую работу для нас из коробки, но текст все еще на английском языке. Угловой не может перевести это автоматически, к сожалению, но может помочь нам с частями рабочего процесса. Это то, что должно произойти:
Угловая помогает нам с шагами 2 и 4, но в качестве разработчиков нам нужно сделать шаг 1 вручную. Шаг 3, как правило, будет дополнен профессионалом перевода или агентством, используя специальное программное обеспечение для чтения и обновления файла перевода.
Для достижения этого мы должны добавить специальный атрибут каждому элементу, который содержит фиксированный текст, который будет переведен. Чтобы быть понятным, если контент поступает из API, то это не фиксированный текст, и вам нужно будет локализовать, что в API. Вам нужно только добавить атрибут, когда текст написан непосредственно в шаблоне HTML в исходном коде. Ключевым моментом здесь является то, что вы должны попытаться сохранить файлы Tearpcript Files Locale-Agnostic - другими словами, избегайте помещения, который необходимо перевести в логику компонентов и сохранить все это в шаблонах. В противном случае инструмент извлечения не сможет извлечь его. В любом случае хорошая практика, чтобы отделить ваши проблемы - в жизни и в коде.
Давайте откроем «app.component.html» и начните с заголовка «текущего значения». Просто добавьте атрибут «I18N» к элементу, который напрямую содержит текст.
& lt; class = "meta__title" i18n & gt;
Текущая стоимость
& lt; / div & gt;
Важно понимать, что это просто «тупой» пользовательский атрибут. Это не угловая директива, которая ничего не вызывает во время выполнения, на самом деле компилятор удаляет его после перевода.
В любом случае, давайте посмотрим, что произойдет, когда мы снова запустим инструмент извлечения, чтобы восстановить файл перевода. Помните «--out-файл» - это просто «Messages.xlf» сейчас:
$ ng xi18n --output-path locale --out-файл
messages.xlf --i18n-locale AR-IQ
Откройте файл выхода XLF, и вы должны увидеть новый блок блок перевода, который выглядит что-то подобное с некоторыми дополнительной информацией контекста:
& lt; Транс-единица ID = "face3d45c0f0cd38b726e7798da15
3E2F8D55551 «DataType =« HTML »и GT;
& lt; источник и GT;
Текущая стоимость
& lt; / Источник и GT;
Отлично, что означает, что инструмент поднял атрибут «I18N». Этот длинный идентификатор генерируется инструментом и останется прежним, если текстовые не изменится. Если у вас есть несколько экземпляров точно такого же текста, они все будут получить тот же идентификатор. Не редактируйте этот идентификатор!
Если вы предпочитаете, вы можете указать пользовательский идентификатор в атрибуте «I18N». Если вы сделаете это, идентификатор останется прежним, даже если текст меняется, поэтому вы должны быть уверены, что у вас нет никаких идентификаций идентификаций в вашем приложении. Используйте префикс «@@», чтобы установить пользовательский идентификатор. Здесь удостоверение личности станет «титулом»:
& lt; class = "meta__title" i18n = "@@ title" и gt;
Текущая стоимость
& lt; / div & gt;
Чтобы переводчик мог дать точный перевод, им часто нужно знать контекст, в котором используется текст. Атрибут «I18N» позволяет нам определить описание и значение, чтобы помочь переводчику. Формат выглядит следующим образом:
& lt; div i18n = "значение | Описание @@
customid "& gt; текст & lt; / div & gt;
Давайте обновим наш заголовок со значением и описанием:
& lt; class = "meta__title" i18n = "карта
Название | Значение в этот момент во времени @@ title "& gt;
Текущая стоимость
& lt; / div & gt;
Это должно дать достаточный контекст переводчика, чтобы обеспечить точный перевод. Восстановите файл перевода, и вы должны увидеть, как эти значения были выведены. Стоит отметить, что если вы не используете пользовательский идентификатор, сгенерированный идентификатор принимает значение и текст. Так же тот же текст, но с другим значением, получит другой идентификатор. Описание, однако, не влияет на идентификатор.
Давайте перейдем к секции в Intro. Первый абзац содержит текст и переменную, которая будет интерполирована во время выполнения. Как мы обращаемся к этому?
Ну, счастливо, это довольно просто. Опять же, нам нужно добавить значимый атрибут «i18n» к содержащему элементу. Добавьте его непосредственно в элемент абзаца:
& lt; p i18n = "Закрывающее значение | Значение, когда рынок
закрыто вчера @@ closingValue "& gt;
Запустите инструмент извлечения еще раз, и вы увидите этот новый блок перевода:
& lt; транс-агрегат ID = "ClosingValue"
datatype = "html" & gt;
& lt; источник и gt; вчерашний день закрытия APOS;
& lt; x id = "интерполяция" equiv-text = "{{
ClosingValue |. валюта: & amp; apos; gbp & amp; apos;
}} "/ & gt;. & lt; [/ source & gt;
Посмотрите, как переменная интерполяция была детализирована на выходе. Приятная вещь в этом - это позволяет переводчику изменять грамматическую структуру предложения при необходимости, не нарушая связывание. Например, может быть язык, где предложение будет лучше всего написано: x Значение было вчерашнее закрытие, то есть с переменной в начале.
Переход к следующему абзацу вы увидите некоторое запугивающий синтаксис. Это называется форматом сообщений ICU, и он позволяет указывать различные кусочки текста на основе значения переменной.
Вы можете использовать это, чтобы добавить слова на слова на английском, когда значение равно нулю или нет. Например, если «секунды» - это переменная, содержащая количество секунд, мы можем использовать это выражение ICU Pluralisionsation:
{{секунды}} {секунды, множественное число, один
{вторым}, другие {секунды}}
Который будет выводить:
Это не должно быть задокументировано, но вы также можете использовать «AsyncPipe» внутри синтаксиса плюрализы для работы с наблюдателями.
В этом примере «один» и «другие» являются категориями плюральности. Есть ряд категорий для выбора, но остерегайтесь! Не все локалисты поддерживают все категории, и угловые не говорят вам, если вы попытаетесь использовать категорию, которая не поддерживается текущей локалью. Легко в конечном итоге, думать, что вы сделали что-то не так, потому что категория «Два» не работает в вашем локали «en-GB» и вместо этого вы видите «другой» текст. Необъяснимо 'en' (и многие другие общие языки) только поддерживают «один» и «другие», хотя «ноль» и «два» являются явными значениями.
Проверьте этот файл чтобы увидеть, что на самом деле поддерживается.
Мы можем работать вокруг этого ограничения, используя цифры вместо категорий. Просто префикс значения с помощью «=»:
Там {наблюдатели, множественное число, = 0 {никто не} = 1
{один человек} = 2 {два человека}
Другое {{{watchers}} Люди}}
смотреть прямо сейчас.
Это уже настроено в демонстрационном приложении, нам просто нужно добавить атрибут «I18N» в содержащий абзац:
& lt; p i18n = "Наблюдатели | Количество людей
наблюдая за ценностью @@ наблюдателей "& gt;
Запустите инструмент извлечения еще раз, чтобы увидеть, как это выглядит. Вы увидите, что это выводится немного по-разному. Это создаст два трансляции; один для самого выражения ICU и, который интерполизирует это выражение в исходную строку.
Если вы хотите отобразить другой текст в зависимости от значения переменной, вы можете использовать выражение «выбора» ICU, которое очень похоже на синтаксис «множественного числа», продемонстрированный выше. В нашем демонстрационном приложении мы отслеживаем изменение, применяемые к значению и создаем наблюдаемый поток, называемый «Trend $», который выводит «вверх», «вниз» или «стабильный» в зависимости от того, является ли изменение положительным, отрицательным или ноль.
Затем мы подключим наш «выберите» выражение ICU для вывода другой строки в зависимости от значения потока. Здесь вы можете увидеть «AsyncPipe» в использовании:
значение {Trend $ | async, выберите, вверх
{Увеличенный} вниз
{не изменил}}
Это несколько более чистого синтаксиса, чем использование «NGIF» или «NGSwitch», чтобы манипулировать DOM, плюс он также хорошо играет с инструментом извлечения. Добавьте атрибут «I18N» на содержащий элемент:
& lt; class = "card__info" i18n = "
Trend | описывает ценность изменения Trend @@ Trend "& gt;
Восстановите файл переводов, и вы увидите, что подход аналогичен объему множественной продукции, с созданными двумя единицами перевода. Выражения ICU довольно удобны, когда вы привыкаете к ним, плюс вы можете закрыть их, чтобы создать более сложные выходы.
Еще один атрибут i18n 'для добавления:
& lt; class = "card__info" i18n = "
Count | Количество транзакций сегодня @@
транзакции "& gt;
Транзакции: {{{{транзакции $ | async |.
номер }}
& lt; / div & gt;
Теперь мы отмечали весь текст, который необходимо перевести, мы можем генерировать файл перевода в последний раз. Как только он создан переименовать его на «Messages.ar-iq.xlf» и замените предыдущее воплощение. Это файл, который мы отправим на профессионал перевода, но для целей этого учебника Google Translate будет стоять!
Откройте файл XLF и дублируйте каждый «& lt; источник и GT»; элемент, переименовая его «& lt; target & gt;». К сожалению, это может быть совершенно неопрятно, поэтому это может помочь украсить содержание.
Чтобы проверить, у нас все они все, сохраните файл и начните приложение с арабским языком:
$ NG служат --configuration = AR-IQ
Если вы видите какие-либо сообщения в таковом терминале, как это означает, что вы пропустили один:
Ошибка в ошибках разбора XLIFF: сообщение * ID *
пропускает перевод ("
Надеюсь, у вас не будет никаких ошибок, и вы сможете увидеть приложение в браузере. Мы еще не добавили какой-либо фактический арабский язык, так что оно не будет выглядеть так сильно.
Давайте начнем с чего-то проста - заголовок «текущего значения». Google Translate говорит мне, что это должно быть (арабский текст здесь), поэтому обновите значение в «A & LT; Target & GT»; элемент:
& lt; источник и gt; текущее значение & lt; / source & gt;
& lt; target & gt; арабский текст здесь & lt; / target & gt;
Все идет нормально. Теперь давайте сделаем одно с интерполяцией. Вот «вчерашнее закрытие было ...» (надеюсь,!):
& lt; target & gt; арабский текст здесь & lt; x
ID = "интерполяция" equiv-text = "{{closingValue
|. валюта: & amp; apos; gbp & amp; apos; }} "/>.< ;/target>
Используйте номер при переводе, чтобы вы могли видеть, где должен быть интерполяция. Обратите внимание, что, когда вы видите переведенный результат в Google Translate, он будет отображаться обратным - то есть число в начале - но когда вы копируете и вставьте его в файл перевода, он вернется к исходному заказу. Это происходит потому, что арабский язык является языком RTL, поэтому скрипт (почти) полностью отражается. Google Translate делает это, добавив атрибут «dir =» RTL для содержащего элемента. Мы научимся сделать это на следующем шаге. Остальные переводы доступны в демо-репо, «Учебное пособие».
Нам нужно управлять направлением скрипта в нашем приложении, потому что угловые не будут делать это автоматически для нас. Там нет никаких способов обнаружения, если текущий локаль является LTR или RTL-языком, поэтому нам понадобится жесткий код. Было бы здорово, если бы углозно предложил встроенную директиву для этого.
Откройте «app.component.ts». Импортируйте «ввод», «locale_id» и «HOVELBINDING» из «@ угловой / ядра». Затем настройте «HostBinding» следующим образом. Это добавит атрибут «Dir» к AppComponent и устанавливает направление языка по умолчанию на «LTR»:
@hostbinding ('attr.dir') dir = 'ltr';
Далее добавьте конструктор и введите «local_id». Помните, что это устанавливается нашей конфигурацией, потому что мы используем AOT.
Конструктор (@inject (locale_id) Частный локаль: строка) {}
И, наконец, добавьте следующий фрагмент в существующий метод «Ngoninit». Здесь мы проверяем, начинается ли «locale_ID», т. Е. «Ar-IQ», и, если он изменяет направление на «RTL» вместо этого.
Если (this.locale.startswith ('ar')) {
this.dir = 'rtl';
}
Если вы планируете поддержать больше локалей, то вам, вероятно, понадобится рефактору это, чтобы сделать его более масштабируемым, однако, так как сегодня существует только около десяти языков RTL, используемый сегодня, этот подход не должен быть слишком громоздким. Запустите арабское приложение, и теперь вы должны увидеть, что UI отражается - знак £ должен быть справа.
Последний шаг - генерировать и проверять наши производственные сборки. Во-первых, мы должны сделать еще одну быструю модификацию на конфигурацию «angular.json».
В «Architection.Build.configurations» дублируют существующий объект производства и переименуйте его «« Production-AR-IQ ». Затем скопируйте и вставьте свойства из существующей конфигурации «AR-IQ» в объект, поэтому у вас есть как параметры производства, так и параметры «I18N».
Вам также необходимо обновить «Architection.serve.Configurations». На этот раз дублируют существующий объект «AR-IQ» и переименовывают его «« Production-AR-IQ »и измените значение« Browsertarget », чтобы указать на новую конфигурацию« Production-AR-IQ ».
Теперь вы можете построить и обслуживать свой производственный арабский язык с этой командой:
$ ng Подавать --configuration = Production-AR-IQ
Хорошо, мы закончили! Мы успешно интернационализировали наше приложение и локализовали его для аудитории «en-GB» и «AR-IQ». Угловой делает процесс удивительно простым для разработчика, на самом деле, самым сложным битом выясняется, что должны быть переведены - извинения любым арабским колонкам, если что-то не так!
Эта статья была первоначально опубликована в номере 281 Treative Web Design Web Designer. Купить проблему 281 здесь или же Подписаться на веб-дизайнер здесь Отказ
Статьи по Теме:
Если вы не принимаете меры предосторожности с вашим кодом JavaScript, вы пр�..
Только ощущается только вчера, когда я играл роль с друзьями в старших классах в фантазиях мира, полных р..
Анимация в Интернете здесь, чтобы остаться. Это во всем от тонких движе..
Tymdercript - одна из групп языков, которые используют Javascript Время в�..
Этот учебник WebGL демонстрирует, как создать трехмерное симуляцию прир�..
Карта Макеты сайта взяли через Интернет. Сделано популярным Pin..
Поговорка может быть: «Не судите книгу по ее обложке», но дизайн обложки может, на самом деле, сделать или..
Учусь Как нарисовать мангу нет простого подвига. Итак, чтобы сделать его легко проще, я следую пр..