По ходу своей работы я сталкиваюсь с маленькими задачами, которые отнимают много времени (при решении «в лоб»). Иногда получается найти средства для быстрого решения этих задач, иногда нет. Во втором случае, чаще всего, я быстренько пишу собственные маленькие программы, которые позволяют максимально упросить решение задачи.
Недавно столкнулся с одной такой задачей. Всё чаще стала возникать необходимость перевести какой-то текст. То на иврите нужно перевести абзац, то на китайском сайте нужно было почитать обсуждение, то при написании письма зарубежным коллегам не получается перевести «хитрое» предложение — приходится обращаться к онлайн сервисам перевода («подглядеть», что подскажут). Я пользовался сервисами ПРОМТ и Google. Такой подход мне начал надоедать, и я за пару вечеров набросал контекстный переводчик, который использует сразу три сервиса от компаний: Google (Google Translator), Microsoft (Bing Translator), ПРОМТ (мобильная версия).
Уверен, что мои наработки кому-то окажутся полезными.
Эту мини-статью я разделю на две части. Первая посвящена тем, кто хочет просто установить программу и пользоваться ей. А вторая, тем только делает первые шаги в освоение разработки «под» Mac OS X и iPhone (сделали первую программа «Конвертер» по руководству от Apple, но уже имеющие желание писать коммерческое ПО).
Переlator — это простой, но достаточно удобный контекстный переводчик для Mac OS X. Возможны баги, сбои — детально я его не тестировал (не было нужды), но у меня он несколько дней работает нормально.
Компания Apple в Mac OS X 10.6 (Snow Leopard) наконец-то обратила внимание на функционал Services (Службы) и очень хорошо «причесала» его. Переlator базируется на этом функционале.
УСТАНОВКА
1). Скопируйте Translation.service в папку Services:
[ДОМАШНЯЯ ПАПКА]/Библиотеки/Services — если сервис нужен только Вам.
/Библиотеки/Services — если сервис нужен всем пользователям в системе.
Если папки Services не оказалось в необходимом месте, то просто создайте её.
2). Два раза щёлкаем мышкой по сервису (запускаем) или выполняем выход и вход в систему.
3). Открываем Системные настройки > Клавиатура > Службы. Ставим галочку напротив «Перевести» («Translate») и задаём удобное клавиатурное сокращение.
4). Всё. Контекстный переводчик полностью готов к работе.
ИСПОЛЬЗОВАНИЕ
В любой программе, которая поддерживает Службы (Safari, Mail, Skype, iChat, TextEdit, Pages и пр.) выделяем текст, нажимаем правой кнопкой мыши для вызова контекстного меню и выбираем «Перевести» («Translate») — под курсором откроется окно с переводом. Или выделите текст и нажмите заданное клавиатурное сокращение.
Важное замечание… Некоторые программы (особенно кросс-платформенные) не поддерживают функционал Службы.
Переlator для каждого перевода использует собственное окно. Т.е. предыдущий окно с предыдущим перевод не закрывается при переводе нового текста.
Вы можете настроить удобный для Вас размер окна переводчика. Достаточно просто подстроить окно под необходимый размер, и все следующие окна будет идентичного размера.
Провайдер услуги перевода автоматически сохраняется. Например, если Вы в последнем окне выбрали Microsoft, то следующий перевод автоматически отобразить перевод от Microsoft.
В настройках программы Вы можете задать размер шрифта перевода и пару языков для перевода по умолчанию.
Если язык не поддерживается провайдером, мы увидим соответствующее сообщение.
Скачать программу можно по ссылке: http://www.yuriev.info/translator/translator.zip
Системные требования: Mac OS X 10.6 и выше
ОГРАНИЧЕНИЯ
В программа не позволяет переводить очень длинные тексты (в техническом смысле длина запроса не должна превышать 2000 символов). В программе используются методы GET, а не POST.
В программе используется мобильный вариант ПРОМТ (m.translate.ru), которые может переводить только небольшие абзацы.
ДЛЯ НАЧИНАЮЩИЙ РАЗРАБОТЧИКОВ
Я собрал тут ряд банальных и не очень вопросов (которые актуальны для Переlator) и дал на них ответы.
Как создавать HUD интерфейс?
Компания Apple для разработчиков представляет только лишь HUD панель. Все элементы пользователь должен создавать самостоятельно или использовать готовые библиотеки. Я использовал BGHUDAppKit.
Как сохранить и загрузить определённые настройки программы?
Используйте класс NSUserDefaults.
Как задать содержимое NSPopUpButton?
Например, так:
Как задать цвет текста на кнопке?
Как применить CoreImage эффекты к окну (например, сделать размытие как Windows)?
Без использования приватного API не обойтись.
Объявляем:
Задаём фильтр:
…
Убираем фильтр:
Как получить доступ к NSView объекту заголовка окна (для размещения там каких-то дополнительных элементов, например, замочка, как в Safari)?
Как получить текущие координаты курсора мыши?
Как изменить шрифт у всего содержимого объекта NSTextView?
Как программно задать начальную позицию в NSTextView (скроллинг в самое начало)?
Как скрыть какой-нибудь объект класса NSView (например, кнопку)?
Как изменить контекстное меню текстовых объектов?
Нужно задать метод делегата. Вот как это реализовано в программе:
Как отправлять запросы (и получать ответы) к онлайн-сервисам перевода (например, Google, Microsoft)?
Можно воспользоваться стандартным классом NSURLConnection. Я предпочёл воспользоваться сторонним классом GDataHTTPFetcher из проекта gdata-objectivec-client компании Google. Работать объектом этого класса очень просто. Вот код запроса из программы:
Где GoogleURL — это ajax.googleapis.com/ajax/services/language/translate?v=1.0
Недавно столкнулся с одной такой задачей. Всё чаще стала возникать необходимость перевести какой-то текст. То на иврите нужно перевести абзац, то на китайском сайте нужно было почитать обсуждение, то при написании письма зарубежным коллегам не получается перевести «хитрое» предложение — приходится обращаться к онлайн сервисам перевода («подглядеть», что подскажут). Я пользовался сервисами ПРОМТ и Google. Такой подход мне начал надоедать, и я за пару вечеров набросал контекстный переводчик, который использует сразу три сервиса от компаний: Google (Google Translator), Microsoft (Bing Translator), ПРОМТ (мобильная версия).
Уверен, что мои наработки кому-то окажутся полезными.
Эту мини-статью я разделю на две части. Первая посвящена тем, кто хочет просто установить программу и пользоваться ей. А вторая, тем только делает первые шаги в освоение разработки «под» Mac OS X и iPhone (сделали первую программа «Конвертер» по руководству от Apple, но уже имеющие желание писать коммерческое ПО).
Переlator — это простой, но достаточно удобный контекстный переводчик для Mac OS X. Возможны баги, сбои — детально я его не тестировал (не было нужды), но у меня он несколько дней работает нормально.
Компания Apple в Mac OS X 10.6 (Snow Leopard) наконец-то обратила внимание на функционал Services (Службы) и очень хорошо «причесала» его. Переlator базируется на этом функционале.
УСТАНОВКА
1). Скопируйте Translation.service в папку Services:
[ДОМАШНЯЯ ПАПКА]/Библиотеки/Services — если сервис нужен только Вам.
/Библиотеки/Services — если сервис нужен всем пользователям в системе.
Если папки Services не оказалось в необходимом месте, то просто создайте её.
2). Два раза щёлкаем мышкой по сервису (запускаем) или выполняем выход и вход в систему.
3). Открываем Системные настройки > Клавиатура > Службы. Ставим галочку напротив «Перевести» («Translate») и задаём удобное клавиатурное сокращение.
4). Всё. Контекстный переводчик полностью готов к работе.
ИСПОЛЬЗОВАНИЕ
В любой программе, которая поддерживает Службы (Safari, Mail, Skype, iChat, TextEdit, Pages и пр.) выделяем текст, нажимаем правой кнопкой мыши для вызова контекстного меню и выбираем «Перевести» («Translate») — под курсором откроется окно с переводом. Или выделите текст и нажмите заданное клавиатурное сокращение.
Важное замечание… Некоторые программы (особенно кросс-платформенные) не поддерживают функционал Службы.
Переlator для каждого перевода использует собственное окно. Т.е. предыдущий окно с предыдущим перевод не закрывается при переводе нового текста.
Вы можете настроить удобный для Вас размер окна переводчика. Достаточно просто подстроить окно под необходимый размер, и все следующие окна будет идентичного размера.
Провайдер услуги перевода автоматически сохраняется. Например, если Вы в последнем окне выбрали Microsoft, то следующий перевод автоматически отобразить перевод от Microsoft.
В настройках программы Вы можете задать размер шрифта перевода и пару языков для перевода по умолчанию.
Если язык не поддерживается провайдером, мы увидим соответствующее сообщение.
Скачать программу можно по ссылке: http://www.yuriev.info/translator/translator.zip
Системные требования: Mac OS X 10.6 и выше
ОГРАНИЧЕНИЯ
В программа не позволяет переводить очень длинные тексты (в техническом смысле длина запроса не должна превышать 2000 символов). В программе используются методы GET, а не POST.
В программе используется мобильный вариант ПРОМТ (m.translate.ru), которые может переводить только небольшие абзацы.
ДЛЯ НАЧИНАЮЩИЙ РАЗРАБОТЧИКОВ
Я собрал тут ряд банальных и не очень вопросов (которые актуальны для Переlator) и дал на них ответы.
Как создавать HUD интерфейс?
Компания Apple для разработчиков представляет только лишь HUD панель. Все элементы пользователь должен создавать самостоятельно или использовать готовые библиотеки. Я использовал BGHUDAppKit.
Как сохранить и загрузить определённые настройки программы?
Используйте класс NSUserDefaults.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *source = [defaults objectForKey:@"SourceLanguage"];
...
[defaults setObject:language forKey:@"SourceLanguage"];
* This source code was highlighted with Source Code Highlighter.
Как задать содержимое NSPopUpButton?
Например, так:
[sourceLanguagesButton removeAllItems];
[sourceLanguagesButton addItemWithTitle:NSLocalizedString(@"auto", @"")];
[[sourceLanguagesButton menu] addItem:[NSMenuItem separatorItem]];
for (int i = 0; i < 10; i++)
{
[sourceLanguagesButton addItemWithTitle:[NSString stringWithFormat:@"%i", i]];
}
* This source code was highlighted with Source Code Highlighter.
Как задать цвет текста на кнопке?
[contactButton setTitle:NSLocalizedString(@"Contact", @"")];
NSMutableAttributedString *colorTitle = [[NSMutableAttributedString alloc] initWithAttributedString:[contactButton attributedTitle]];
[colorTitle addAttribute:NSForegroundColorAttributeName value:[NSColor whiteColor] range:NSMakeRange(0, [colorTitle length])];
[contactButton setAttributedTitle:colorTitle];
[colorTitle addAttribute:NSForegroundColorAttributeName value:[NSColor blackColor] range:NSMakeRange(0, [colorTitle length])];
[contactButton setAttributedAlternateTitle:colorTitle];
[colorTitle release];
* This source code was highlighted with Source Code Highlighter.
Как применить CoreImage эффекты к окну (например, сделать размытие как Windows)?
Без использования приватного API не обойтись.
Объявляем:
typedef void *CGSWindowFilterRef;
typedef int CGSConnectionID;
typedef int CGSWindowID;
extern CGSConnectionID _CGSDefaultConnection(void);
extern CGError CGSNewCIFilterByName(CGSConnectionID cid, CFStringRef filterName, CGSWindowFilterRef *outFilter);
extern CGError CGSAddWindowFilter(CGSConnectionID cid, CGSWindowID wid, CGSWindowFilterRef filter, int flags);
extern CGError CGSRemoveWindowFilter(CGSConnectionID cid, CGSWindowID wid, CGSWindowFilterRef filter);
extern CGError CGSReleaseCIFilter(CGSConnectionID cid, CGSWindowFilterRef filter);
extern CGError CGSSetCIFilterValuesFromDictionary(CGSConnectionID cid, CGSWindowFilterRef filter, CFDictionaryRef filterValues);
* This source code was highlighted with Source Code Highlighter.
Задаём фильтр:
CGSWindowID wid;
CGSWindowFilterRef fid;
* This source code was highlighted with Source Code Highlighter.
…
int compositingType = 1;
wid = [[self window] windowNumber];
CGSNewCIFilterByName(_CGSDefaultConnection(), (CFStringRef)@"CIGaussianBlur", &fid);
NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:3.0] forKey:@"inputRadius"];
CGSSetCIFilterValuesFromDictionary(_CGSDefaultConnection(), fid, (CFDictionaryRef)options);
CGSAddWindowFilter(_CGSDefaultConnection(), wid, fid, compositingType);
* This source code was highlighted with Source Code Highlighter.
Убираем фильтр:
if (fid)
{
CGSRemoveWindowFilter(_CGSDefaultConnection(), wid, fid);
CGSReleaseCIFilter(_CGSDefaultConnection(), fid);
}
* This source code was highlighted with Source Code Highlighter.
Как получить доступ к NSView объекту заголовка окна (для размещения там каких-то дополнительных элементов, например, замочка, как в Safari)?
NSView *titlebar = [[self.window standardWindowButton:NSWindowCloseButton] superview];
* This source code was highlighted with Source Code Highlighter.
Как получить текущие координаты курсора мыши?
NSPoint point = [NSEvent mouseLocation];
* This source code was highlighted with Source Code Highlighter.
Как изменить шрифт у всего содержимого объекта NSTextView?
[textView setFont:[NSFont systemFontOfSize:20]];
* This source code was highlighted with Source Code Highlighter.
Как программно задать начальную позицию в NSTextView (скроллинг в самое начало)?
NSPoint top;
if([textView isFlipped])
{
top = NSMakePoint(0.0, 0.0);
}
else
{
top = NSMakePoint(0.0, NSMaxY([textView frame]) - NSHeight([textView bounds]));
}
[textView scrollPoint:top];
* This source code was highlighted with Source Code Highlighter.
Как скрыть какой-нибудь объект класса NSView (например, кнопку)?
[object setHidden:YES];
* This source code was highlighted with Source Code Highlighter.
Как изменить контекстное меню текстовых объектов?
Нужно задать метод делегата. Вот как это реализовано в программе:
- (NSMenu *)textView:(NSTextView *)view menu:(NSMenu *)menu forEvent:(NSEvent *)event atIndex:(NSUInteger)charIndex
{
NSMenuItem *spotlight = nil;
NSMenuItem *google = nil;
NSMenuItem *dictionary = nil;
NSMenuItem *copy = nil;
NSMenuItem *speech = nil;
int count = [menu numberOfItems];
for (int i = 0; i < count; i++)
{
SEL action = [[menu itemAtIndex:i] action];
if (action == @selector(spotlight:))
{
spotlight = [[menu itemAtIndex:i] retain];
}
else if (action == @selector(_searchWithGoogleFromMenu:))
{
google = [[menu itemAtIndex:i] retain];
}
else if (action == @selector(_lookUpDefiniteRangeInDictionaryFromMenu:))
{
dictionary = [[menu itemAtIndex:i] retain];
}
else if (action == @selector(copy:))
{
copy = [[menu itemAtIndex:i] retain];
}
else if (action == @selector(submenuAction:))
{
NSMenu *submenu = [[menu itemAtIndex:i] submenu];
if (submenu)
{
if ([submenu numberOfItems] == 2)
{
if ([[submenu itemAtIndex:0] action] == @selector(startSpeaking:))
{
speech = [[menu itemAtIndex:i] retain];
}
}
}
}
}
if (!copy)
{
if (spotlight) [spotlight release];
if (google) [google release];
if (dictionary) [dictionary release];
if (speech) [speech release];
return menu;
}
[menu removeAllItems];
if (spotlight) [menu addItem:spotlight], [spotlight release];
if (google) [menu addItem:google], [google release];
if (dictionary) [menu addItem:dictionary], [dictionary release];
if ([menu numberOfItems] > 0) [menu addItem:[NSMenuItem separatorItem]];
[menu addItem:copy], [copy release];
if (speech)
{
[menu addItem:[NSMenuItem separatorItem]];
[menu addItem:speech], [speech release];
}
return menu;
}
* This source code was highlighted with Source Code Highlighter.
Как отправлять запросы (и получать ответы) к онлайн-сервисам перевода (например, Google, Microsoft)?
Можно воспользоваться стандартным классом NSURLConnection. Я предпочёл воспользоваться сторонним классом GDataHTTPFetcher из проекта gdata-objectivec-client компании Google. Работать объектом этого класса очень просто. Вот код запроса из программы:
NSString *sourceText = [originalText stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *langs = [[NSString stringWithFormat:@"%@|%@", sourceLanguage, targetLanguage] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *requestURL = [NSString stringWithFormat:@"%@&q=%@&langpair=%@", GoogleURL, sourceText, langs];
NSURL *url = [NSURL URLWithString:requestURL];
NSURLRequest* request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:20.0];
fetcherG = [[GDataHTTPFetcher httpFetcherWithRequest:request] retain];
[fetcherG beginFetchWithDelegate:self
didFinishSelector:@selector(httpFetcher:finishedWithData:)
didFailSelector:@selector(httpFetcher:didFail:)];
* This source code was highlighted with Source Code Highlighter.
Где GoogleURL — это ajax.googleapis.com/ajax/services/language/translate?v=1.0