2. О чем пойдет речь
Задача: делаем Single page application.
Или расширение для Хрома.
Или приложение на PhoneGap.
Или приложение для социальной сети.
Или свою социальную сеть.
Или вообще любой современный сайт.
3. О чем пойдет речь
Общие задачи решают фреймворки.
Рассмотрим две частные (на самом деле не
связанные, зато интересные) задачи:
1. Как вывести много картинок.
2. Как выводить много текста.
4. Часть 1. Укладка изображений
(layout то есть, но раз уж вторая часть про
локализацию…)
В этой части будет много картинок.
5. Цель?
● Выводим картинки или текст, HTML?
● Много (лента), мало (альбом) или очень
мало (запись с аттачами)?
● Можно сжимать и обрезать?
● Можно менять местами?
● Можно таскать, редактировать,
анимировать?
7. Квадратики+
Если на некоторых фото
хочется сделать акцент —
делаем их в 4 раза больше.
Требуется чтобы число столбцов было
четным (бонус: укладка на одном CSS).
Используется: Facebook
8. А если не квадрат?
Вариант А: сжимать
+ всё на месте
– дырки
– всё мелкое
Вариант Б: обрезать
+ аккуратные поля
– потери
– иногда потери
критические
(портреты?)
9. Сделаем поинтереснее
Пусть можно сжимать, но очень не хочется
обрезать И оставлять пустые «дырки».
Bin Packing Problem:
NP-полнота, нужен
перебор всех комбинаций.
10. (Почти) идеальное решение
Фиксированная высота строки, ничего не
обрезано, везде равные поля.
Используется: поиск
Google, Яндекс,
iOS-приложение ВК
(в альбомах).
11. Как эта магия работает?
Сколько бы картинок ни было в строке, их
можно сделать равной высоты, а суммарную
ширину — равной ширине строки.
«Набиваем» их, пока высота > minRowHeight
12. ...и когда эта магия не работает?
● В небольших альбомах висячая
последняя строка портит вид.
● У широооких фоток (ландшафты,
панорамы) преимущество перед
высокими (портреты).
● Строки немного плавают по высоте.
13. Когда фоток совсем мало
Перебираем, сколько положим на каждую
строчку и из всех вариантов выбираем
оптимальный по
пропорциям/размеру.
Используется: ВК
(в постах)
14. А если столбики, а не строки?
Если порядок не особо
важен, можно просто
заполнять столбики.
Чит: ещё можно выбирать ширину столбиков
как-нибудь по-хитрому.
Используется: tumblr, Pinterest, Lightbox
15. Дополнительный чит
Подгоняем под сетку, когда соседние
столбики выровнялись — вставляем
широкую картинку, становится не так скучно.
17. Экзотика: золотое сечение
Пользуемся тем, что из двух ландшафтов
четко формируется один портрет (и наоборот).
– У портретов или
у ландшафтов перевес.
– Квадратам места нет.
– Висячий хвост в конце.
18. Как всё это применить?
Например, Masonry:
Или Packery.
Или Isotope.
Все упаковывают,
никто не масштабирует: не для картинок.
http://masonry.desandro.com/
http://packery.metafizzy.co/
19. Как всё это применить?
Или вот Freewall:
плагин jQuery.
Поддерживает
4 укладки, перетаскивание и анимации.
http://vnjs.net/www/project/freewall/
20. (Почти) идеальное решение+
Внутрь строк прячем стопки! Наполняем
почти как строки — пока можем.
Теперь широкие фотки
складываются в стопки,
а не забивают всю строку.
21. + Можно гибко настраивать размеры строк и
стопок.
+ Альтернативный режим: подгонять все
фото под искомую площадь. Бонус: можно
делать акценты (задать искомую площадь
побольше).
– Те же проблемы с последней строкой.
– Строки по-прежнему могут плавать.
24. Для рендеринга в opts передаем функцию:
renderTile: function(tile, path) {
…
return html;
},
path содержит тройку индексов row, stack и
tile – номер строчки, стопки и картинки в
стопке.
Использование
28. Часть 2. Об интернационализации
(и локализации тоже)
● язык = ru, en
● локаль = ru_RU, en_US, en_GB
● перевод = отображение ключей на строки
● интернационализация = i18n = подготовка
● локализация = l10n = процесс перевода
29. А нужны ли эти заморочки?
Нужны.
● Задел на будущее.
● Избавление от «Найдено 21 фотографий».
● Возможность править тексты без правки
шаблонов.
30. Начнем с простого
Все строки кладем в виде полей куда-нибудь
в lang { … }, а потом достаем по lang[‘key’].
Сразу же хочется научиться делать
подстановки (интерполировать) — пишем
функцию:
function T(key, substitute) { … }
31. А что там с числами?
Всё страшно.
В каждом языке свои
категории. До шести
штук. ШЕСТИ, КАРЛ.
http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html
32. Половой вопрос
Тут чуть проще: только два случая (если не
придираться).
Придется спрашивать ещё одно поле при
регистрации, зато никаких уродливых
«Загрузил(а)».
33. Число, род… и падеж, конечно
Тут всё совсем плохо. Даже для одного
языка фамилии склоняются по
неоднозначно определенным правилам:
Чаплин → Чаплином или Чаплиным?
Повезло тем, у кого в языке падежей нет.
Решение: Petrovich.js
34. Работа с датами
Тут всё чуть иначе: формат зависит от
локали, а не от языка.
Но от языка зависят фразы типа «3 часа
назад», которые хорошо бы тоже уметь
выводить с умом.
Решение: moment.js, разумеется.
35. Работа с числами
Всё аналогично датам, только заморочек с
выводом относительного времени нет.
Решение: Numeral.js или сами фреймворки
36. А как же .toLocaleString()?
В ванильном JS есть:
Date.prototype.toLocaleString()
Number.prototype.toLocaleString()
Есть давно, но настроить можно только с
Chrome 24, FF 29, IE 11, Opera 15, а в Safari
до сих пор нельзя.
37. А неплохо бы ещё...
...вспомнить о типографских правилах.
● кроме «-» есть, как минимум, «—» и «–»
● кавычки бывают “тоже” «разные»
● автозамены: (c) , (r) , (tm) , ...
● и вообще много всего
Решения: Типограф, mdash.ru, грамотность.
38. Итого:
Для i18n + l10n:
● l10n.js
● LocalePlanet
● L20n от Mozilla
● Moment.js – даты
● Numeral.js – числа
● Petrovich.js – имена
● Типограф – правила
Ближе всего к тому, что надо: FormatJS.io и
i18next.com (но все равно не идеально)
+
39. У всех свои форматы :(
i18next:
{ en: { translation: {
girlsAndBoys:
'$t(girls, {"count": __girls__})
and __count__ boy',
girlsAndBoys_plural:
'$t(girls, {"count": __girls__})
and __count__ boys' },
girls: '__count__ girl',
girls_plural: '__count__ girls'
} } };
FormatJS:
‘You have {itemCount, plural,
=0 {no items}
one {1 item}
other {{itemCount} items}
}.’
Это хотя бы стандарт
Message ICU
Но он совсем адовый
40. Хочется всего и сразу
Но без излишеств (встроенного во
фреймворки не хватает, тащить кучу
библиотек ради базовых вещей грустно). К
тому же, вещи реально тесно связанные.
Склонять имена вообще все боятся.
41. Мое решение?
Да, ещё один велосипед. С блекджеком и
своим форматом шаблонов.
T.js
https://github.com/deNULL/T.js
42. Это почти как шаблонизатор, но нет
photos: 'фотографий',
liked: 'оценил',
user_liked: '{user} {>liked} {photos} {>photos}',
Делаем: T(‘user_liked’, {user: ’Олег’, photos: 5})
и получаем: ‘Олег оценил 5 фотографий’.
Подставили входные данные + другие ключи.
43. Структура языковых данных
T.define({ ru: {
key1: ‘str1’,
key2: ‘str2’,
key3: { subkey: { subsubkey: ‘wow’ } },
}})
Можно вызывать сколько угодно раз.
Вложенность любая. Достаем через точку:
T(‘key3.subkey.subsubkey’)
44. А что с числами?
Чтобы не было ‘Олег оценил 1 фотографий’:
photos: { $plural: {
one: ‘фотографию’, few: ‘фотографии’,
other: ‘фотографий’
}}
Категории зависят от языка, есть поддержка
ru/en. Можно добавить свою функцию
определения категории.
45. А если не Олег, а Анна?
liked: { $gender: {
m: ‘оценил’, f: ‘оценила’
}}
Аналогично, но надо передавать пол как
параметр в подставляемый шаблон:
user_liked: ‘… {>user.name user.gender} …’
T(‘user_liked’,
{ user: { name: ‘Анна’, gender: ‘f’});
46. А добавить «... Ильи» в конце?
user_liked: ‘… {$name.gen whom.name}’
= вызов функции $name с первым
параметром whom.name, вторым — ‘gen’
(родительный падеж).
Есть внутренние функции $name, $surname,
$patronym для русского, их можно
доопределить или переопределить.
47. Что за «вызов функции»?
Функция = шаблон. Подставить шаблон =
вызвать функцию. Если имя функции или
шаблона начинается с $, то при подстановке
> не нужен ({>$some} = {$some}).
То, что после точек (func.p1.p2)
интерпретируется как дополнительные
параметры.
49. И внезапно — инлайн-перевод
T.inlineTranslation(true);
TA-DA! Все строки кликабельны и открывают
окошко с текстом перевода.
Сохранение изменений (и проверка прав) на
сервере — лежит на вас.
T.showAllKeys();
Показать вообще все ключики списком.
50. Такая вот красота
Это всё без дополнительных зависимостей.
Можно и вырезать, если юзер не переводчик.
51. К слову
T(‘user!’) — Локально отключить инлайн.
Инлайн-перевод генерит HTML — в
шаблонизаторы надо подставлять результат
в сыром виде (Angular: $sce + ng-bind-html).
Во входных данных эскейпятся < и > – а в
самих переводах нет, будьте внимательны.
52. Чего пока нет
● форматирование дат ({$date …})
● форматирование чисел ({$num …})
Под некоторым сомнением: применение
типографских правил.