diff --git a/Gemfile b/Gemfile index abd43e80f..9ac50afa0 100644 --- a/Gemfile +++ b/Gemfile @@ -30,6 +30,7 @@ gem "bourbon", "~> 5.1" gem "buffer", "~> 0.1" gem "carrierwave", "~> 1.3" gem "carrierwave-bombshelter", "~> 0.2" +gem "cld", "~> 0.8" gem "cloudinary", "~> 1.11" gem "counter_culture", "~> 2.1" gem "csv_shaper", "~> 1.3" diff --git a/Gemfile.lock b/Gemfile.lock index 0a426ebbc..3fc6130fd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -199,6 +199,8 @@ GEM chromedriver-helper (2.1.0) archive-zip (~> 0.10) nokogiri (~> 1.8) + cld (0.8.0) + ffi cloudinary (1.11.1) aws_cf_signer rest-client @@ -1009,6 +1011,7 @@ DEPENDENCIES carrierwave (~> 1.3) carrierwave-bombshelter (~> 0.2) chromedriver-helper (~> 2.1) + cld (~> 0.8) cloudinary (~> 1.11) counter_culture (~> 2.1) csv_shaper (~> 1.3) diff --git a/app/assets/javascripts/initializers/initializeFetchFollowedArticles.js.erb b/app/assets/javascripts/initializers/initializeFetchFollowedArticles.js.erb index 91da86a09..d718d23e7 100644 --- a/app/assets/javascripts/initializers/initializeFetchFollowedArticles.js.erb +++ b/app/assets/javascripts/initializers/initializeFetchFollowedArticles.js.erb @@ -35,6 +35,7 @@ function insertNewArticles(user){ var intersectedTags = intersect_arrays(user.followed_tag_names, article.cached_tag_list_array) var followedPoints = 1 var experienceDifference = Math.abs(article['experience_level_rating'] - user.experience_level || 5) + var containsPreferredLanguage = findOne([article.language || 'en'], user.preferred_languages_array || ['en']); JSON.parse(user.followed_tags).map(function(tag) { if (intersectedTags.includes(tag.name)) { followedPoints = followedPoints + tag.points @@ -47,6 +48,11 @@ function insertNewArticles(user){ if (containsOrganizationID) { articlePoints = articlePoints + 16 } + if (containsPreferredLanguage) { + articlePoints = articlePoints + 1 + } else { + articlePoints = articlePoints - 10 + } var rand = Math.random(); if (rand < 0.3) { articlePoints = articlePoints + 1 @@ -80,6 +86,7 @@ function insertTopArticles(user){ var intersectedTags = intersect_arrays(user.followed_tag_names, article.cached_tag_list_array) var followedPoints = 1 var experienceDifference = Math.abs(article['experience_level_rating'] - user.experience_level || 5) + var containsPreferredLanguage = findOne([article.language || 'en'], user.preferred_languages_array || ['en']) JSON.parse(user.followed_tags).map(function(tag) { if (intersectedTags.includes(tag.name)) { followedPoints = followedPoints + tag.points @@ -98,6 +105,11 @@ function insertTopArticles(user){ } else if (rand < 0.6) { articlePoints = articlePoints + 3 } + if (containsPreferredLanguage) { + articlePoints = articlePoints + 1 + } else { + articlePoints = articlePoints - 10 + } articlePoints = articlePoints - (experienceDifference/2); article['points'] = articlePoints }); @@ -115,6 +127,7 @@ function insertTopArticles(user){ function algoliaFollowedArticles(){ var user = userData(); + if (user && user.followed_tag_names && user.followed_tag_names.length > 0) { insertInitialArticles(user) var followedUsersArray = []; diff --git a/app/controllers/async_info_controller.rb b/app/controllers/async_info_controller.rb index 67f68fa12..8b449409b 100644 --- a/app/controllers/async_info_controller.rb +++ b/app/controllers/async_info_controller.rb @@ -48,6 +48,7 @@ class AsyncInfoController < ApplicationController display_sponsors: @user.display_sponsors, trusted: @user.trusted, experience_level: @user.experience_level, + preferred_languages_array: @user.preferred_languages_array, config_body_class: @user.config_body_class } end diff --git a/app/controllers/stories_controller.rb b/app/controllers/stories_controller.rb index 7039d2806..41da14266 100644 --- a/app/controllers/stories_controller.rb +++ b/app/controllers/stories_controller.rb @@ -104,7 +104,7 @@ class StoriesController < ApplicationController def handle_base_index @home_page = true @page = (params[:page] || 1).to_i - num_articles = 30 + num_articles = 35 @stories = article_finder(num_articles) add_param_context(:page, :timeframe) if %w[week month year infinity].include?(params[:timeframe]) diff --git a/app/decorators/user_decorator.rb b/app/decorators/user_decorator.rb index 1c36560d1..81e95d17e 100644 --- a/app/decorators/user_decorator.rb +++ b/app/decorators/user_decorator.rb @@ -83,4 +83,12 @@ class UserDecorator < ApplicationDecorator ] colors[id % 10] end + + def preferred_languages_array + languages = [] + language_settings.keys.each do |setting| + languages << setting.split("prefer_language_")[1] if language_settings[setting] && setting.include?("prefer_language_") + end + languages + end end diff --git a/app/labor/language_detector.rb b/app/labor/language_detector.rb index 0803fd911..2d24adda6 100644 --- a/app/labor/language_detector.rb +++ b/app/labor/language_detector.rb @@ -5,26 +5,17 @@ class LanguageDetector def detect response = get_language - response["result"] if response["confidence"] > 0.8 + response[:code] if response[:reliable] rescue StandardError nil end def get_language - return { "result" => "en", "confidence" => 0.9 } unless Rails.env.production? - - client = Algorithmia.client(ApplicationConfig["ALGORITHMIA_KEY"]) - algo = client.algo("miguelher/LanguageDetector/0.1.0") - algo.pipe(text).result + CLD.detect_language(text) end def text - @article.title + "\n" + - non_default_description.to_s + + @article.title + ". " + FrontMatterParser::Parser.new(:md).call(@article.body_markdown).content.split("`")[0] end - - def non_default_description - @article.description + "\n" unless @article.description.include? "From the DEV community" - end end diff --git a/app/models/article.rb b/app/models/article.rb index 400048ad0..2d1b6c2db 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -80,7 +80,7 @@ class Article < ApplicationRecord :comments_count, :positive_reactions_count, :cached_tag_list, :main_image, :main_image_background_hex_color, :updated_at, :slug, :video, :user_id, :organization_id, :video_source_url, :video_code, - :video_thumbnail_url, :video_closed_caption_track_url, + :video_thumbnail_url, :video_closed_caption_track_url, :language, :experience_level_rating, :experience_level_rating_distribution, :published_at, :crossposted_at, :boost_states, :description, :reading_time, :video_duration_in_seconds) } @@ -142,7 +142,7 @@ class Article < ApplicationRecord id: :index_id, per_environment: true, enqueue: :trigger_delayed_index do - attributes :title, :path, :class_name, :comments_count, :reading_time, + attributes :title, :path, :class_name, :comments_count, :reading_time, :language, :tag_list, :positive_reactions_count, :id, :hotness_score, :score, :readable_publish_date, :flare_tag, :user_id, :organization_id, :cloudinary_video_url, :video_duration_in_minutes, :experience_level_rating, :experience_level_rating_distribution attribute :published_at_int do diff --git a/app/models/user.rb b/app/models/user.rb index 058fec29e..0e37ee2c2 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -189,6 +189,7 @@ class User < ApplicationRecord prefer_language_es Boolean, default: false prefer_language_fr Boolean, default: false prefer_language_it Boolean, default: false + prefer_language_pt Boolean, default: false end def self.trigger_delayed_index(record, remove) diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb index 3c3d8a6b9..7ee2beda7 100644 --- a/app/policies/user_policy.rb +++ b/app/policies/user_policy.rb @@ -106,6 +106,7 @@ class UserPolicy < ApplicationPolicy prefer_language_es prefer_language_fr prefer_language_it + prefer_language_pt prefer_language_ja profile_image seeking_mentorship diff --git a/app/views/stories/_main_stories_feed.html.erb b/app/views/stories/_main_stories_feed.html.erb index b6cd0a656..f08fe1206 100644 --- a/app/views/stories/_main_stories_feed.html.erb +++ b/app/views/stories/_main_stories_feed.html.erb @@ -10,7 +10,7 @@
<%= f.label :config_theme, "Site Theme" %> - <%= f.select(:config_theme, options_for_select(["default", "night theme"], @user.config_theme.gsub("_", " "))) %> + <%= f.select(:config_theme, options_for_select(["default", "night theme"], @user.config_theme.tr("_", " "))) %> Default is light style. Night theme is in public alpha.
<%= f.label :config_font, "Base Post Font" %> - <%= f.select(:config_font, options_for_select(["default", "sans serif", "comic sans"], @user.config_font.gsub("_", " "))) %> + <%= f.select(:config_font, options_for_select(["default", "sans serif", "comic sans"], @user.config_font.tr("_", " "))) %> Default is serif style.
@@ -81,6 +81,10 @@ <%= f.check_box :prefer_language_it %> <%= f.label :prefer_language_it, "Italian" %>
+
+ <%= f.check_box :prefer_language_pt %> + <%= f.label :prefer_language_pt, "Portugese" %> +
diff --git a/spec/labor/language_detector_spec.rb b/spec/labor/language_detector_spec.rb index 0f040b3a0..a71ae1af3 100644 --- a/spec/labor/language_detector_spec.rb +++ b/spec/labor/language_detector_spec.rb @@ -3,8 +3,22 @@ require "rails_helper" RSpec.describe LanguageDetector do let(:user) { create(:user) } let(:article) { create(:article, user_id: user.id) } + let(:article_1) { create(:article, user_id: user.id) } + let(:article_2) { create(:article, user_id: user.id) } - it "returns language" do + it "detects english" do + article.update_column(:body_markdown, "This is definitely english.") + article.update_column(:title, "I love the english language.") expect(described_class.new(article).detect).to eq("en") end + it "detects french" do + article_1.update_column(:body_markdown, "C'est vraiment francais, bien oui?") + article_1.update_column(:title, "C'est vraiment francais, bien oui?") + expect(described_class.new(article_1).detect).to eq("fr") + end + it "detects nil if non-sensicle" do + article_2.update_column(:body_markdown, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec pharetra sapien orci, sit amet auctor nunc tempor quis.") + article_2.update_column(:title, "Mauris commodo felis et lacus volutpat fermentum.") + expect(described_class.new(article_2).detect).to eq(nil) + end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index e8c931ec7..d176e5a65 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -380,6 +380,12 @@ RSpec.describe User, type: :model do new_user = user_from_authorization_service(:twitter, nil, "navbar_basic") new_user.estimate_default_language_without_delay! end + + it "returns proper preferred_languages_array" do + user.email = "ben@hello.jp" + user.estimate_default_language_without_delay! + expect(user.decorate.preferred_languages_array).to include("ja") + end end it "follows users" do