diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index df0ce18e..b753dfd6 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -48,7 +48,7 @@ class ItemsController < ApplicationController respond_to do |format| format.html do - unless fragment_exist?("items/#{@item.id} contributors") + unless localized_fragment_exist?("items/#{@item.id} contributors") @contributors_with_counts = @item.contributors_with_counts end diff --git a/app/helpers/closet_hangers_helper.rb b/app/helpers/closet_hangers_helper.rb index fa9c5d37..a80364f8 100644 --- a/app/helpers/closet_hangers_helper.rb +++ b/app/helpers/closet_hangers_helper.rb @@ -137,5 +137,15 @@ module ClosetHangersHelper hangers = @unlisted_closet_hangers_by_owned[owned] hangers ? hangers.size : 0 end + + def closet_lists_group_name(subject, owned) + ownership_key = owned ? 'owned_by' : 'wanted_by' + if subject == :you + translate "closet_lists.groups.#{ownership_key}.you" + else + translate "closet_lists.groups.#{ownership_key}.another_user", + :user_name => subject.name + end + end end diff --git a/app/helpers/items_helper.rb b/app/helpers/items_helper.rb index 07e2d1a9..2aeafae4 100644 --- a/app/helpers/items_helper.rb +++ b/app/helpers/items_helper.rb @@ -102,6 +102,11 @@ module ItemsHelper def auction_genie_url_for(item) "http://www.neopets.com/genie.phtml?type=process_genie&criteria=exact&auctiongenie=#{CGI::escape item.name}" end + + def trading_closet_hangers_header(owned, count) + ownership_key = owned ? 'owned' : 'wanted' + translate ".trading_closet_hangers.header.#{ownership_key}", :count => count + end def render_trading_closet_hangers(owned) @trading_closet_hangers_by_owned[owned].map do |hanger| diff --git a/app/models/contribution_observer.rb b/app/models/contribution_observer.rb index 50ddb798..2c232cdc 100644 --- a/app/models/contribution_observer.rb +++ b/app/models/contribution_observer.rb @@ -6,7 +6,7 @@ class ContributionObserver < ActiveRecord::Observer if contribution.contributed_type == 'SwfAsset' item = contribution.contributed.item - expire_fragment("items/#{item.id} contributors") + expire_fragment_in_all_locales("items/#{item.id} contributors") end end end diff --git a/app/models/item_observer.rb b/app/models/item_observer.rb index ab8e0c76..167581ca 100644 --- a/app/models/item_observer.rb +++ b/app/models/item_observer.rb @@ -20,8 +20,8 @@ class ItemObserver < ActionController::Caching::Sweeper def expire_cache_for(item) expire_fragment("items/#{item.id}#item_link_partial") - expire_fragment("items/#{item.id} header") - expire_fragment("items/#{item.id} info") + expire_fragment_in_all_locales("items/#{item.id} header") + expire_fragment_in_all_locales("items/#{item.id} info") end def expire_newest_items diff --git a/app/views/items/show.html.haml b/app/views/items/show.html.haml index f42b738c..3358ce08 100644 --- a/app/views/items/show.html.haml +++ b/app/views/items/show.html.haml @@ -1,31 +1,32 @@ - title @item.name - canonical_path @item -- cache "items/#{@item.id} header" do +- localized_cache "items/#{@item.id} header" do %header#item-header = image_tag @item.thumbnail_url, :id => 'item-thumbnail' %div %h2#item-name= @item.name = nc_icon_for(@item) - unless @item.rarity.blank? - == Rarity: #{@item.rarity_index} (#{@item.rarity}) - = link_to 'JN Items', jn_items_url_for(@item) + == #{t '.rarity'}: #{@item.rarity_index} (#{@item.rarity}) + = link_to t('.jn_items'), jn_items_url_for(@item) - unless @item.nc? - = link_to 'Shop Wizard', shop_wizard_url_for(@item) - = link_to 'Super Wizard', super_shop_wizard_url_for(@item) - = link_to 'Trades', trading_post_url_for(@item) - = link_to 'Auctions', auction_genie_url_for(@item) + = link_to t('.shop_wizard'), shop_wizard_url_for(@item) + = link_to t('.super_shop_wizard'), super_shop_wizard_url_for(@item) + = link_to t('.trading_post'), trading_post_url_for(@item) + = link_to t('.auction_genie'), auction_genie_url_for(@item) - if user_signed_in? #closet-hangers %h3 - Track this in - = link_to 'Your Items', user_closet_hangers_path(current_user) + = t '.hangers_header_html', + :user_items_link => link_to(t('your_items'), + user_closet_hangers_path(current_user)) = form_tag update_quantities_user_item_closet_hangers_path(:user_id => current_user, :item_id => @item), :method => :put do #closet-hangers-ownership-groups - @current_user_lists.each do |owned, lists| %div - %h4 Items you #{closet_list_verb(owned)} + %h4= closet_lists_group_name(:you, owned) %ul - lists.each do |list| %li @@ -38,81 +39,69 @@ @current_user_quantities[owned], :min => 0 - unless lists.empty? - = label_tag "quantity[#{owned}]", :class => 'unlisted' do - Not in a list + = label_tag "quantity[#{owned}]", + t('closet_lists.unlisted_name'), + :class => 'unlisted' - else - = label_tag "quantity[#{owned}]" do - How many? - = submit_tag 'Save to Your Items' + = label_tag "quantity[#{owned}]", t('.quantity_label') + = submit_tag t('.submit_hangers') -- cache "items/#{@item.id} info" do +- localized_cache "items/#{@item.id} info" do %p= @item.description #item-zones %p - %strong Occupies: + %strong #{t '.occupied_zones_header'}: = list_zones @item.occupied_zones, :uncertain_label %p - %strong Restricts: + %strong #{t '.restricted_zones_header'}: - if @item.restricted_zones.empty? - None + = t '.no_restricted_zones' - else = list_zones @item.restricted_zones #trade-hangers - [true, false].each do |owned| %p - - unless @trading_closet_hangers_by_owned[owned].empty? - %strong - = pluralize @trading_closet_hangers_by_owned[owned].size, 'user' - - if owned - - if @trading_closet_hangers_by_owned[owned].size == 1 - has - - else - have - this item up for trade: - - else - - if @trading_closet_hangers_by_owned[owned].size == 1 - wants - - else - want - this item: - = render_trading_closet_hangers(owned) - - else - %strong - We don't know anyone who - - if owned - has this item up for trade. - - else - wants this item. + %strong + = trading_closet_hangers_header(owned, @trading_closet_hangers_by_owned[owned].size) + = render_trading_closet_hangers(owned) %span.toggle - %span.more more - %span.less less + %span.more= t '.trading_closet_hangers.show_more' + %span.less= t '.trading_closet_hangers.show_less' -- cache 'items#show preview_header' do +- localized_cache 'items#show preview_header' do #item-preview-header - %h3 Preview - %a#customize-more.button{:href => '/'} Customize more + %h3= t '.preview_header' + = link_to t('.customize_more'), root_path, :id => 'customize-more', + :class => 'button' #item-preview #item-preview-species= standard_species_images_for(@item) #item-preview-error - #item-preview-swf - Javascript and Flash are required to preview wearables. Sorry! + #item-preview-swf= t '.preview_requirements_not_met' -- cache "items/#{@item.id} contributors" do +- localized_cache "items/#{@item.id} contributors" do - unless @contributors_with_counts.empty? #item-contributors - %header Brought to you by: + %header #{t '.contributors_header'}: %ul - @contributors_with_counts.each do |contributor, count| %li= link_to(contributor.name, user_contributions_path(contributor)) + format_contribution_count(count) - %footer Thanks! + %footer= t '.contributors_footer' :javascript var CURRENT_ITEM_ZONES_RESTRICT = #{@item.zones_restrict.inspect}, IMPRESS_HOST = #{RemoteImpressHost.inspect}; -= include_javascript_libraries :jquery, :swfobject -= javascript_include_tag 'items/show' +%script#swf-assets-not-found-template{:type => 'text/x-jquery-tmpl'} + = t '.swf_assets_not_found_html', :item_name => h(@item.name), + :species_name => '${species_name}', + :color_name => '${color_name}', + :modeling_link => link_to(t('.swf_assets_not_found_modeling_link_content'), + root_path) + +- content_for :javascripts do + = include_javascript_libraries :jquery, :swfobject, :jquery_tmpl + = javascript_include_tag 'items/show' diff --git a/config/locales/en-meep.yml b/config/locales/en-meep.yml index dc53737c..78c075e4 100644 --- a/config/locales/en-meep.yml +++ b/config/locales/en-meep.yml @@ -48,6 +48,16 @@ en-meep: converted_at_html: Conveeped %{converted_at_ago} ago reported_at_html: Repeeped %{reported_at_ago} ago + closet_lists: + unlisted_name: Not in a meep + groups: + owned_by: + you: Meeps you own + another_user: Meeps %{user_name} owns + wanted_by: + you: Meeps you want + another_user: Meeps %{user_name} wants + contributions: contributed_description: item_suffix: for the first meep @@ -96,6 +106,43 @@ en-meep: type_example_description: returns any item that fills a "hat" meep newest_items_header: New Meeps species_search_header: Can't decide? Meep by species + + show: + rarity: Meepity + jn_items: JN Meepits + shop_wizard: Meep Wizard + super_shop_wizard: Meeper Wizard + trading_post: Treeps + auction_genie: Aucteeps + hangers_header_html: Meep this in %{user_items_link} + quantity_label: How meepy? + submit_hangers: Save to Your Meeps + occupied_zones_header: Occupeeps + restricted_zones_header: Restreeps + no_restricted_zones: Meepless + trading_closet_hangers: + header: + owned: + zero: We don't know anymeep who has this item meep for trade. + one: "1 user has this item meep for trade:" + other: "%{count} users have this item meep for trade:" + wanted: + zero: "We don't know anymeep who meeps this item." + one: "1 user meeps this item:" + other: "%{count} users meep this item:" + show_more: meep more + show_less: meep less + preview_header: Meepview + customize_more: Customize meep + preview_requirements_not_met: + Javascript and Flash are required to preview meepits. Meep! + contributors_header: Meeped to you by + contributors_footer: Meep! + swf_assets_not_found_html: + We've never meeped the %{item_name} on the %{color_name} + %{species_name} before. Have you? If so, please %{modeling_link} and + we'll meep our datameep instantly. Meep! + swf_assets_not_found_modeling_link_content: meep it for us outfits: new: diff --git a/config/locales/en.yml b/config/locales/en.yml index fac24ccf..cd2a2852 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -49,6 +49,17 @@ en: converted_at_html: Converted %{converted_at_ago} ago reported_at_html: Reported %{reported_at_ago} ago + closet_lists: + unlisted_name: Not in a list + groups: + owned_by: + you: Items you own + another_user: Items %{user_name} owns + wanted_by: + you: Items you want + another_user: Items %{user_name} wants + + contributions: contributed_description: item_suffix: for the first time @@ -97,6 +108,43 @@ en: type_example_description: returns any item that fills a "hat" zone newest_items_header: Newest items species_search_header: Can't decide? Search by species + + show: + rarity: Rarity + jn_items: JN Items + shop_wizard: Shop Wizard + super_shop_wizard: Super Wizard + trading_post: Trades + auction_genie: Auctions + hangers_header_html: Track this in %{user_items_link} + quantity_label: How many? + submit_hangers: Save to Your Items + occupied_zones_header: Occupies + restricted_zones_header: Restricts + no_restricted_zones: None + trading_closet_hangers: + header: + owned: + zero: We don't know anyone who has this item up for trade. + one: "1 user has this item up for trade:" + other: "%{count} users have this item up for trade:" + wanted: + zero: "We don't know anyone who wants this item." + one: "1 user wants this item:" + other: "%{count} users want this item:" + show_more: more + show_less: less + preview_header: Preview + customize_more: Customize more + preview_requirements_not_met: + Javascript and Flash are required to preview wearables. Sorry! + contributors_header: Brought to you by + contributors_footer: Thanks! + swf_assets_not_found_html: + We've never seen the %{item_name} on the %{color_name} + %{species_name} before. Have you? If so, please %{modeling_link} and + we'll update our database instantly. Thanks! + swf_assets_not_found_modeling_link_content: model it for us outfits: new: diff --git a/public/javascripts/items/show.js b/public/javascripts/items/show.js index e02d8a48..bc5548a3 100644 --- a/public/javascripts/items/show.js +++ b/public/javascripts/items/show.js @@ -16,56 +16,29 @@ String.prototype.capitalize = function () { return this.charAt(0).toUpperCase() + this.substr(1); } -String.prototype.article = function () { - return 'aeiou'.indexOf(this.charAt(0).toLowerCase()) == -1 ? 'a' : 'an' -} - function impressUrl(path) { return 'http://' + IMPRESS_HOST + path; } -function LoadError(base_msg) { - this.render = function (args) { - var msg = base_msg, token, article_token; - for(var i in args) { - token = "$" + i; - article_token = token + "_article"; - if(msg.indexOf(article_token) != -1) { - msg = msg.replace(article_token, args[i].article()); - } - msg = msg.replace(token, args[i]); - } - return "Whoops - we've never seen " + msg + " before! If you have, please " + - "submit that pet's name as soon as you " + - "get the chance! Thanks!"; - } -} - function PetType() { var pet_type = this, loaded_data = false, loaded_assets = false; this.activated = true; this.assets = []; - this.deactivate = function (error, args) { + this.deactivate = function () { var msg; this.activated = false; - if(typeof args == 'undefined') args = {}; - args.color = this.color_name.capitalize(); - args.species = this.species_name.capitalize(); - this.deactivation_msg = error.render(args); + this.deactivation_msg = $('#swf-assets-not-found-template').tmpl({ + color_name: this.color_name.capitalize(), + species_name: this.species_name.capitalize() + }); if(this == PetType.current) showDeactivationMsg(); var img = this.link.children('img').get(0); this.link.addClass('deactivated'); img.src = img.src.replace('/1/', '/2/'); } - this.deactivateWithItem = function (item) { - pet_type.deactivate(Item.LOAD_ERROR, { - item: item.name - }); - } - this.load = function () { Item.current.load(this); loadAssets(); @@ -108,8 +81,6 @@ function PetType() { } PetType.all = {}; - -PetType.LOAD_ERROR = new LoadError("$color_article $color $species"); PetType.DASH_REGEX = /-/g; PetType.createFromLink = function (link) { @@ -148,7 +119,7 @@ function Item(id) { }); $.each(PetType.all, function () { if(item.getAssetsForPetType(this).length == 0) { - this.deactivateWithItem(item); + this.deactivate(); } }); }); @@ -167,13 +138,11 @@ function Item(id) { this.assets_by_body_id[pet_type.body_id] = assets; pet_type.onUpdate(); } else { - pet_type.deactivateWithItem(this); + pet_type.deactivate(); } } } -Item.LOAD_ERROR = new LoadError("$species_article $species wear a $item"); - Item.createFromLocation = function () { var item = new Item(parseInt(document.location.pathname.substr(7), 10)), z = CURRENT_ITEM_ZONES_RESTRICT, zl = z.length; @@ -197,7 +166,7 @@ Preview = new function Preview() { this.update = function (assets) { var assets; - if(swf) { + if(swf && typeof swf.setAssets == 'function') { log('now doing update'); assets = PetType.current.assets.concat( Item.current.getAssetsForPetType(PetType.current) @@ -228,9 +197,9 @@ Preview = new function Preview() { ); } - this.disable = function (msg) { + this.disable = function (errorMessage) { $('#' + swf_id).hide(); - $('#item-preview-error').html(msg).show(); + $('#item-preview-error').empty().append(errorMessage).show(); } this.enable = function () {