mirror of
				https://github.com/Foundry376/Mailspring.git
				synced 2025-10-25 21:46:31 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			145 lines
		
	
	
	
		
			5.1 KiB
		
	
	
	
		
			CoffeeScript
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
	
		
			5.1 KiB
		
	
	
	
		
			CoffeeScript
		
	
	
	
	
	
| # # Translation Plugin
 | |
| # Last Revised: April 23, 2015 by Ben Gotow
 | |
| #
 | |
| # TranslateButton is a simple React component that allows you to select
 | |
| # a language from a popup menu and translates draft text into that language.
 | |
| #
 | |
| 
 | |
| request = require 'request'
 | |
| 
 | |
| {Utils,
 | |
|  React,
 | |
|  ComponentRegistry,
 | |
|  DraftStore} = require 'nylas-exports'
 | |
| {Menu,
 | |
|  RetinaImg,
 | |
|  Popover} = require 'nylas-component-kit'
 | |
| 
 | |
| YandexTranslationURL = 'https://translate.yandex.net/api/v1.5/tr.json/translate'
 | |
| YandexTranslationKey = 'trnsl.1.1.20150415T044616Z.24814c314120d022.0a339e2bc2d2337461a98d5ec9863fc46e42735e'
 | |
| YandexLanguages =
 | |
|   'English': 'en'
 | |
|   'Spanish': 'es'
 | |
|   'Russian': 'ru'
 | |
|   'Chinese': 'zh'
 | |
|   'French': 'fr'
 | |
|   'German': 'de'
 | |
|   'Italian': 'it'
 | |
|   'Japanese': 'ja'
 | |
|   'Portuguese': 'pt'
 | |
|   'Korean': 'ko'
 | |
| 
 | |
| class TranslateButton extends React.Component
 | |
| 
 | |
|   # Adding a `displayName` makes debugging React easier
 | |
|   @displayName: 'TranslateButton'
 | |
| 
 | |
|   # Since our button is being injected into the Composer Footer,
 | |
|   # we receive the local id of the current draft as a `prop` (a read-only
 | |
|   # property). Since our code depends on this prop, we mark it as a requirement.
 | |
|   #
 | |
|   @propTypes:
 | |
|     draftLocalId: React.PropTypes.string.isRequired
 | |
| 
 | |
|   # The `render` method returns a React Virtual DOM element. This code looks
 | |
|   # like HTML, but don't be fooled. The CJSX preprocessor converts
 | |
|   #
 | |
|   # `<a href="http://facebook.github.io/react/">Hello!</a>`
 | |
|   #
 | |
|   # into Javascript objects which describe the HTML you want:
 | |
|   #
 | |
|   # `React.createElement('a', {href: 'http://facebook.github.io/react/'}, 'Hello!')`
 | |
|   #
 | |
|   # We're rendering a `Popover` with a `Menu` inside. These components are part
 | |
|   # of N1's standard `nylas-component-kit` library, and make it easy to build
 | |
|   # interfaces that match the rest of N1's UI.
 | |
|   #
 | |
|   render: =>
 | |
|     React.createElement(Popover, {"ref": "popover",  \
 | |
|              "className": "translate-language-picker pull-right",  \
 | |
|              "buttonComponent": (@_renderButton())},
 | |
|       React.createElement(Menu, {"items": ( Object.keys(YandexLanguages) ),  \
 | |
|             "itemKey": ( (item) -> item ),  \
 | |
|             "itemContent": ( (item) -> item ),  \
 | |
|             "onSelect": (@_onTranslate)
 | |
|             })
 | |
|     )
 | |
| 
 | |
|   # Helper method to render the button that will activate the popover. Using the
 | |
|   # `RetinaImg` component makes it easy to display an image from our package.
 | |
|   # `RetinaImg` will automatically chose the best image format for our display.
 | |
|   #
 | |
|   _renderButton: =>
 | |
|     React.createElement("button", {"className": "btn btn-toolbar"}, """
 | |
|       Translate
 | |
| """, React.createElement(RetinaImg, {"name": "toolbar-chevron.png"})
 | |
|     )
 | |
| 
 | |
|   _onTranslate: (lang) =>
 | |
|     @refs.popover.close()
 | |
| 
 | |
|     # Obtain the session for the current draft. The draft session provides us
 | |
|     # the draft object and also manages saving changes to the local cache and
 | |
|     # Nilas API as multiple parts of the application touch the draft.
 | |
|     #
 | |
|     session = DraftStore.sessionForLocalId(@props.draftLocalId)
 | |
|     session.prepare().then =>
 | |
|       body = session.draft().body
 | |
|       bodyQuoteStart = Utils.quotedTextIndex(body)
 | |
| 
 | |
|       # Identify the text we want to translate. We need to make sure we
 | |
|       # don't translate quoted text.
 | |
|       if bodyQuoteStart > 0
 | |
|         text = body.substr(0, bodyQuoteStart)
 | |
|       else
 | |
|         text = body
 | |
| 
 | |
|       query =
 | |
|         key: YandexTranslationKey
 | |
|         lang: YandexLanguages[lang]
 | |
|         text: text
 | |
|         format: 'html'
 | |
| 
 | |
|       # Use Node's `request` library to perform the translation using the Yandex API.
 | |
|       request {url: YandexTranslationURL, qs: query}, (error, resp, data) =>
 | |
|         return @_onError(error) unless resp.statusCode is 200
 | |
|         json = JSON.parse(data)
 | |
| 
 | |
|         # The new text of the draft is our translated response, plus any quoted text
 | |
|         # that we didn't process.
 | |
|         translated = json.text.join('')
 | |
|         translated += body.substr(bodyQuoteStart) if bodyQuoteStart > 0
 | |
| 
 | |
|         # To update the draft, we add the new body to it's session. The session object
 | |
|         # automatically marshalls changes to the database and ensures that others accessing
 | |
|         # the same draft are notified of changes.
 | |
|         session.changes.add(body: translated)
 | |
|         session.changes.commit()
 | |
| 
 | |
|   _onError: (error) =>
 | |
|     @refs.popover.close()
 | |
|     dialog = require('remote').require('dialog')
 | |
|     dialog.showErrorBox('Geolocation Failed', error.toString())
 | |
| 
 | |
| 
 | |
| module.exports =
 | |
|   # Activate is called when the package is loaded. If your package previously
 | |
|   # saved state using `serialize` it is provided.
 | |
|   #
 | |
|   activate: (@state) ->
 | |
|     ComponentRegistry.register TranslateButton,
 | |
|       role: 'Composer:ActionButton'
 | |
| 
 | |
|   # Serialize is called when your package is about to be unmounted.
 | |
|   # You can return a state object that will be passed back to your package
 | |
|   # when it is re-activated.
 | |
|   #
 | |
|   serialize: ->
 | |
| 
 | |
|   # This **optional** method is called when the window is shutting down,
 | |
|   # or when your package is being updated or disabled. If your package is
 | |
|   # watching any files, holding external resources, providing commands or
 | |
|   # subscribing to events, release them here.
 | |
|   #
 | |
|   deactivate: ->
 | |
|     ComponentRegistry.unregister(TranslateButton)
 |