arguments

Mô-đun này cung cấp xử lý dễ dàng các đối số được truyền từ #invoke.

arguments Tài liệu mô đun

Đây là một mô-đun meta, được sử dụng cho các mô-đun khác và không được gọi trực tiếp từ #invoke. Các tính năng của nó bao gồm:

  • Dễ dàng cắt xén các đối số và loại bỏ các đối số trống.
  • Đối số có thể được truyền bởi cả khung hiện tại và khung cha cùng một lúc. (Thêm chi tiết bên dưới.)
  • Các đối số có thể được truyền trực tiếp từ một mô-đun Lua khác hoặc từ bảng điều khiển gỡ lỗi.
  • Đối số được tìm nạp khi cần, điều này có thể giúp tránh (một số) sự cố với thẻ ....
  • Hầu hết các tính năng có thể được tùy chỉnh.

Sử dụng cơ bản

Đầu tiên, bạn cần tải mô-đun. Nó chứa một hàm, được đặt tên getArgs.

local getArgs = require('Module:Arguments').getArgs 

Trong kịch bản cơ bản nhất, bạn có thể sử dụng getArgs bên trong chức năng chính của mình. Biến args là bảng chứa các đối số từ #invoke. (Xem bên dưới để biết chi tiết.)

local getArgs = require('Module:Arguments').getArgs local p = {}  function p.main(frame) local args = getArgs(frame) -- Main module code goes here. end  return p 

Tuy nhiên, thực tế nên đề xuất là sử dụng một hàm chỉ để xử lý các đối số từ #invoke. Điều này có nghĩa là nếu ai đó gọi mô-đun của bạn từ một mô-đun Lua khác, bạn không phải có sẵn một đối tượng khung, điều này giúp cải thiện hiệu suất.

local getArgs = require('Module:Arguments').getArgs local p = {}  function p.main(frame) local args = getArgs(frame) return p._main(args) end  function p._main(args) -- Main module code goes here. end  return p 

Nếu bạn muốn nhiều hàm sử dụng các đối số và bạn cũng muốn chúng có thể truy cập được từ #invoke, bạn có thể sử dụng hàm bao bọc.

local getArgs = require('Module:Arguments').getArgs  local p = {}  local function makeInvokeFunc(funcName) return function (frame) local args = getArgs(frame) return p[funcName](args) end end  p.func1 = makeInvokeFunc('_func1')  function p._func1(args) -- Code for the first function goes here. end  p.func2 = makeInvokeFunc('_func2')  function p._func2(args) -- Code for the second function goes here. end  return p 

Tùy chỉnh

Một só Lựa chọn tùy chỉnh có sẵn khi sử dụng. Chúng được giải thích trong các phần dưới đây.

local args = getArgs(frame, { trim = false, removeBlanks = false, valueFunc = function (key, value) -- Code for processing one argument end, frameOnly = true, parentOnly = true, parentFirst = true, wrappers = { 'Template:A wrapper template', 'Template:Another wrapper template' }, readOnly = true, noOverwrite = true }) 

Cắt và loại bỏ khoảng trống

Các đối số trống thường gây khó đối với các lập trình viên mới muốn chuyển đổi các bản mẫu MediaWiki sang Lua. Trong cú pháp bản mẫu, chuỗi trống và chuỗi chỉ bao gồm khoảng trắng được coi là sai. Tuy nhiên, trong Lua, chuỗi trống và chuỗi bao gồm khoảng trắng được coi là đúng. Điều này có nghĩa là nếu bạn không chú ý đến những lập luận như vậy khi bạn viết các mô-đun Lua của mình, bạn có thể coi điều gì đó là đúng mà thực sự nên được coi là sai. Để tránh điều này, theo mặc định, mô-đun này sẽ xóa tất cả các đối số trống.

Tương tự, khoảng trắng có thể gây ra vấn đề khi xử lý các đối số vị trí. Mặc dù khoảng trắng được cắt bớt cho các đối số được đặt tên đến từ #invoke, nhưng nó được giữ nguyên cho các đối số vị trí. Hầu hết thời gian khoảng trắng bổ sung này là không mong muốn, vì vậy mô-đun này cắt nó theo mặc định.

Tuy nhiên, đôi khi bạn muốn sử dụng các đối số trống làm đầu vào và đôi khi bạn muốn giữ khoảng trắng bổ sung. Điều này có thể cần thiết để chuyển đổi một số mẫu chính xác như chúng đã được viết. Nếu bạn muốn làm điều này, bạn có thể đặt trimremoveBlanks với tham số là false.

local args = getArgs(frame, { trim = false, removeBlanks = false }) 

Định dạng tùy chỉnh của các đối số

Đôi khi bạn muốn xóa một số đối số trống nhưng không phải là đối số khác hoặc có lẽ bạn muốn đặt tất cả các đối số vị trí ở dạng chữ thường. Để làm những việc như thế này bạn có thể sử dụng tùy chọn valueFunc. Đầu vào của tùy chọn này phải là một hàm có hai tham số, keyvalue, và trả về một giá trị duy nhất. Giá trị này là những gì bạn sẽ nhận được khi truy cập vào trường key trong bảng args.

Ví dụ 1: hàm này bảo toàn khoảng trắng cho đối số vị trí đầu tiên, nhưng cắt bỏ tất cả các đối số khác và loại bỏ tất cả các đối số trống khác.

local args = getArgs(frame, { valueFunc = function (key, value) if key == 1 then return value elseif value then value = mw.text.trim(value) if value ~= '' then return value end end return nil end }) 

Ví dụ 2: hàm này loại bỏ các đối số trống và chuyển đổi tất cả các đối số thành chữ thường, nhưng không cắt khoảng trắng khỏi các tham số vị trí.

local args = getArgs(frame, { valueFunc = function (key, value) if not value then return nil end value = mw.ustring.lower(value) if mw.ustring.find(value, '%S') then return value end return nil end }) 

Lưu ý: các chức năng trên sẽ thất bại nếu đầu vào không thuộc loại string hoặc nil. Đây có thể là trường hợp nếu bạn sử dụng chức năng getArgs trong chức năng chính của mô-đun của bạn và chức năng đó được gọi bởi một mô-đun Lua khác. Trong trường hợp này, bạn sẽ cần kiểm tra loại đầu vào của bạn. Đây không phải là vấn đề nếu bạn đang sử dụng một hàm đặc biệt cho các đối số từ #invoke (tức là bạn có chức năng p.mainp._main, hoặc một cái gì đó tương tự).

Ví dụ 1 và 2 với kiểm tra loại

Ví dụ 1:

local args = getArgs(frame, { valueFunc = function (key, value) if key == 1 then return value elseif type(value) == 'string' then value = mw.text.trim(value) if value ~= '' then return value else return nil end else return value end end }) 

Ví dụ 2:

local args = getArgs(frame, { valueFunc = function (key, value) if type(value) == 'string' then value = mw.ustring.lower(value) if mw.ustring.find(value, '%S') then return value else return nil end else return value end end }) 

Ngoài ra, xin lưu ý rằng hàm valueFunc được gọi nhiều hơn hoặc ít hơn mỗi khi một đối số được yêu cầu từ bảng args, vì vậy nếu bạn quan tâm đến hiệu suất mà bạn nên chắc chắn rằng bạn không làm bất cứ điều gì không hiệu quả với mã của bạn.

Khung và khung cha

Đối số trong bảng args có thể được truyền từ khung hiện tại hoặc từ khung chính của nó cùng một lúc. Để hiểu điều này có nghĩa là gì, dễ nhất là đưa ra một ví dụ. Hãy nói rằng chúng ta có một mô-đun gọi là Module:ExampleArgs. Mô-đun này in hai đối số vị trí đầu tiên mà nó được thông qua.

Mã nguồn của Mô đun:ExampleArgs
local getArgs = require('Module:Arguments').getArgs local p = {}  function p.main(frame) local args = getArgs(frame) return p._main(args) end  function p._main(args) local first = args[1] or '' local second = args[2] or '' return first .. ' ' .. second end  return p 

Module:ExampleArgs sau đó được gọi bởi Bản mẫu:ExampleArgs, có chứa đoạn mã {{#invoke:ExampleArgs|main|firstInvokeArg}}. Điều này tạo ra kết quả "firstInvokeArg".

Bây giờ nếu chúng ta gọi Bản mẫu:ExampleArgs, điều sau đây sẽ xảy ra:

Kết quả
{{ExampleArgs}} firstInvokeArg
{{ExampleArgs|firstTemplateArg}} firstInvokeArg
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} firstInvokeArg secondTemplateArg

Có ba tùy chọn bạn có thể đặt để thay đổi hành vi này: frameOnly, parentOnlyparentFirst. Nếu bạn đặt frameOnly sau đó chỉ các đối số được truyền từ khung hiện tại sẽ được chấp nhận; nếu bạn đặt parentOnly sau đó chỉ các đối số được truyền từ khung cha sẽ được chấp nhận; và nếu bạn đặt parentFirst sau đó các đối số sẽ được truyền từ cả khung hiện tại và khung chính, nhưng khung chính sẽ có mức độ ưu tiên so với khung hiện tại. Dưới đây là kết quả với Bản mẫu:ExampleArgs:

    frameOnly
Kết quả
{{ExampleArgs}} firstInvokeArg
{{ExampleArgs|firstTemplateArg}} firstInvokeArg
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} firstInvokeArg
    parentOnly
Kết quả
{{ExampleArgs}}
{{ExampleArgs|firstTemplateArg}} firstTemplateArg
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} firstTemplateArg secondTemplateArg
    parentFirst
Kết quả
{{ExampleArgs}} firstInvokeArg
{{ExampleArgs|firstTemplateArg}} firstTemplateArg
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} firstTemplateArg secondTemplateArg

Chú ý:

  1. Nếu bạn đặt cả hai tùy chọn frameOnlyparentOnly, mô-đun sẽ không tìm nạp bất kỳ đối số nào từ #invoke. Đây có lẽ không phải là những gì bạn muốn.
  2. Trong một số trường hợp, khung cha có thể không khả dụng, ví dụ: nếu getArgs thông qua khung cha chứ không phải khung hiện tại. Trong trường hợp này, chỉ các đối số khung sẽ được sử dụng (trừ khi parentOnly được đặt, trong trường hợp đó sẽ không có đối số nào được sử dụng) và tùy chọn parentFirstframeOnly sẽ không có tác dụng.

Wrappers

Tùy chon wrappers được sử dụng để chỉ định một số lượng bản mẫu giới hạn như Bản mẫu wrapper, đó là, các bản mẫu có mục đích duy nhất là gọi một mô-đun. Nếu mô-đun phát hiện ra rằng nó đang được gọi từ một bản mẫu wrappers, nó sẽ chỉ kiểm tra các đối số trong khung cha; nếu không, nó sẽ chỉ kiểm tra các đối số trong khung được truyền cho getArgs. Điều này cho phép các mô-đun được gọi bằng #invoke hoặc thông qua mẫu wrappers mà không làm giảm hiệu suất liên quan đến việc phải kiểm tra cả khung và khung chính cho mỗi lần tra cứu đối số.

Ví dụ: nội dung duy nhất của Template:Side box (trừ nội dung trong cặp ...) là {{#invoke:Side box|main}}. Không có điểm nào trong việc kiểm tra các đối số được truyền trực tiếp vào câu lệnh #invoke cho bản mẫu này, vì sẽ không có đối số nào được chỉ định ở đó. Chúng ta có thể tránh việc kiểm tra các đối số được truyền cho #invoke bằng cách sử dụng tùy chọn parentOnly, nhưng nếu chúng ta làm điều này thì #invoke cũng sẽ không hoạt động từ các trang khác. Nếu đây là trường hợp, |text=Some text trong mã {{#invoke:Side box|main|text=Some text}} sẽ bị bỏ qua hoàn toàn, bất kể nó được sử dụng từ trang nào. Bằng cách sử dụng tùy chọn wrappers để cụ thể hóa 'Bản mẫu:Side box' là một wrapper, ta có thể tạo {{#invoke:Side box|main|text=Some text}} hoạt động từ hầu hết các trang, trong khi vẫn không yêu cầu mô-đun kiểm tra các đối số trên chính trang Bản mẫu:Side box.

Wrappers có thể được chỉ định là một chuỗi hoặc là một chuỗi các chuỗi.

local args = getArgs(frame, { wrappers = 'Template:Wrapper template' }) 


local args = getArgs(frame, { wrappers = { 'Template:Wrapper 1', 'Template:Wrapper 2', -- Bất kì số nào của bản mẫu wrapper cũng có thể thêm vào đây. } }) 

Chú ý:

  1. Mô-đun sẽ tự động phát hiện nếu nó được gọi từ trang con /sandbox của bản mẫu wrapper, do đó không cần chỉ định rõ ràng các trang sandbox.
  2. Tùy chọn wrappers thay đổi hiệu quả mặc định của tùy chọn frameOnlyparentOnly. Nếu, ví dụ, parentOnly rõ ràng được đặt thành false với set wrappers, các cuộc gọi thông qua các bàn mẫu Wrapper sẽ dẫn đến cả hai đối số khung và đối số được tải, mặc dù các cuộc gọi không qua các mẫu trình bao bọc sẽ chỉ dẫn đến các đối số khung được tải.
  3. Nếu tùy chọn wrappers được đặt và không có khung cha nào khả dụng, mô-đun sẽ luôn nhận được các đối số từ khung được truyền cho getArgs.

Viết vào bảng args

Đôi khi nó có thể hữu ích để viết các giá trị mới vào bảng args. Điều này là có thể với các thiết lập mặc định của mô-đun này. (Tuy nhiên, hãy nhớ rằng thường là phong cách mã hóa tốt hơn để tạo một bảng mới với các giá trị mới của bạn và sao chép các đối số từ bảng args khi cần.)

args.foo = 'some value' 

Có thể thay đổi hành vi này với tùy chọn readOnlynoOverwrite. Nếu readOnly được đặt thì không thể ghi bất kỳ giá trị nào vào bảng args. Nếu noOverwrite được đặt, sau đó có thể thêm các giá trị mới vào bảng, nhưng không thể thêm giá trị nếu nó ghi đè lên bất kỳ đối số nào được truyền từ #invoke.

Cập tags Ref

Mô đun này sử dụng metatables để tìm nạp các đối số từ #invoke. Điều này cho phép truy cập vào cả đối số khung và đối số khung cha mà không cần sử dụng hàm chức năng pairs(). Điều này có thể giúp có ích nếu mô-đun của bạn có thể được thông qua tags ... làm đầu vào.

Ngay khi Tags ... được truy cập từ Lua, chúng được xử lý bởi phần mềm MediaWiki và tài liệu tham khảo sẽ xuất hiện trong danh sách tham khảo ở cuối bài viết. Nếu mô-đun của bạn tiến hành bỏ qua thẻ tham chiếu từ đầu ra, bạn sẽ kết thúc bằng một tham chiếu ảo - một tham chiếu xuất hiện trong danh sách tham chiếu, nhưng không có số nào liên kết với nó. Đây là một vấn đề với các mô-đun sử dụng pairs() để phát hiện xem nên sử dụng các đối số từ khung hoặc khung cha, vì các mô-đun đó tự động xử lý mọi đối số có sẵn.

Mô-đun này giải quyết vấn đề này bằng cách cho phép truy cập vào cả đối số khung và khung cha, trong khi vẫn chỉ tìm nạp các đối số đó khi cần thiết. Vấn đề vẫn sẽ xảy ra nếu bạn sử dụng pairs(args) ở nơi khác trong mô-đun của bạn, tuy nhiên.

Những hạn chế đã biết

Việc sử dụng các metatables cũng có nhược điểm của nó. Hầu hết các công cụ bảng Lua bình thường sẽ không hoạt động chính xác trên bảng args, bao gồm cả mã hoạt động #, hàm chức năng next(), và các chức năng trong thư viện bảng. Nếu việc sử dụng này là quan trọng cho mô-đun của bạn, bạn nên sử dụng chức năng xử lý đối số của riêng bạn thay vì mô-đun này.

-- This module provides easy processing of arguments passed to Scribunto from -- #invoke. It is intended for use by other Lua modules, and should not be -- called from #invoke directly.  local libraryUtil = require('libraryUtil') local checkType = libraryUtil.checkType  local arguments = {}  -- Generate four different tidyVal functions, so that we don't have to check the -- options every time we call it.  local function tidyValDefault(key, val) if type(val) == 'string' then val = val:match('^%s*(.-)%s*$') if val == '' then return nil else return val end else return val end end  local function tidyValTrimOnly(key, val) if type(val) == 'string' then return val:match('^%s*(.-)%s*$') else return val end end  local function tidyValRemoveBlanksOnly(key, val) if type(val) == 'string' then if val:find('%S') then return val else return nil end else return val end end  local function tidyValNoChange(key, val) return val end  local function matchesTitle(given, title) local tp = type( given ) return (tp == 'string' or tp == 'number') and mw.title.new( given ).prefixedText == title end  local translate_mt = { __index = function(t, k) return k end }  function arguments.getArgs(frame, options) checkType('getArgs', 1, frame, 'table', true) checkType('getArgs', 2, options, 'table', true) frame = frame or {} options = options or {}  --[[ -- Set up argument translation. --]] options.translate = options.translate or {} if getmetatable(options.translate) == nil then setmetatable(options.translate, translate_mt) end if options.backtranslate == nil then options.backtranslate = {} for k,v in pairs(options.translate) do options.backtranslate[v] = k end end if options.backtranslate and getmetatable(options.backtranslate) == nil then setmetatable(options.backtranslate, { __index = function(t, k) if options.translate[k] ~= k then return nil else return k end end }) end  --[[ -- Get the argument tables. If we were passed a valid frame object, get the -- frame arguments (fargs) and the parent frame arguments (pargs), depending -- on the options set and on the parent frame's availability. If we weren't -- passed a valid frame object, we are being called from another Lua module -- or from the debug console, so assume that we were passed a table of args -- directly, and assign it to a new variable (luaArgs). --]] local fargs, pargs, luaArgs if type(frame.args) == 'table' and type(frame.getParent) == 'function' then if options.wrappers then --[[ -- The wrappers option makes Module:Arguments look up arguments in -- either the frame argument table or the parent argument table, but -- not both. This means that users can use either the #invoke syntax -- or a wrapper template without the loss of performance associated -- with looking arguments up in both the frame and the parent frame. -- Module:Arguments will look up arguments in the parent frame -- if it finds the parent frame's title in options.wrapper; -- otherwise it will look up arguments in the frame object passed -- to getArgs. --]] local parent = frame:getParent() if not parent then fargs = frame.args else local title = parent:getTitle():gsub('/sandbox$', '') local found = false if matchesTitle(options.wrappers, title) then found = true elseif type(options.wrappers) == 'table' then for _,v in pairs(options.wrappers) do if matchesTitle(v, title) then found = true break end end end  -- We test for false specifically here so that nil (the default) acts like true. if found or options.frameOnly == false then pargs = parent.args end if not found or options.parentOnly == false then fargs = frame.args end end else -- options.wrapper isn't set, so check the other options. if not options.parentOnly then fargs = frame.args end if not options.frameOnly then local parent = frame:getParent() pargs = parent and parent.args or nil end end if options.parentFirst then fargs, pargs = pargs, fargs end else luaArgs = frame end  -- Set the order of precedence of the argument tables. If the variables are -- nil, nothing will be added to the table, which is how we avoid clashes -- between the frame/parent args and the Lua args. local argTables = {fargs} argTables[#argTables + 1] = pargs argTables[#argTables + 1] = luaArgs  --[[ -- Generate the tidyVal function. If it has been specified by the user, we -- use that; if not, we choose one of four functions depending on the -- options chosen. This is so that we don't have to call the options table -- every time the function is called. --]] local tidyVal = options.valueFunc if tidyVal then if type(tidyVal) ~= 'function' then error( "giá trị xấu được gán cho tùy chọn 'valueFunc'" .. '(chức năng mong đợi, có ' .. type(tidyVal) .. ')', 2 ) end elseif options.trim ~= false then if options.removeBlanks ~= false then tidyVal = tidyValDefault else tidyVal = tidyValTrimOnly end else if options.removeBlanks ~= false then tidyVal = tidyValRemoveBlanksOnly else tidyVal = tidyValNoChange end end  --[[ -- Set up the args, metaArgs and nilArgs tables. args will be the one -- accessed from functions, and metaArgs will hold the actual arguments. Nil -- arguments are memoized in nilArgs, and the metatable connects all of them -- together. --]] local args, metaArgs, nilArgs, metatable = {}, {}, {}, {} setmetatable(args, metatable)  local function mergeArgs(tables) --[[ -- Accepts multiple tables as input and merges their keys and values -- into one table. If a value is already present it is not overwritten; -- tables listed earlier have precedence. We are also memoizing nil -- values, which can be overwritten if they are 's' (soft). --]] for _, t in ipairs(tables) do for key, val in pairs(t) do if metaArgs[key] == nil and nilArgs[key] ~= 'h' then local tidiedVal = tidyVal(key, val) if tidiedVal == nil then nilArgs[key] = 's' else metaArgs[key] = tidiedVal end end end end end  --[[ -- Define metatable behaviour. Arguments are memoized in the metaArgs table, -- and are only fetched from the argument tables once. Fetching arguments -- from the argument tables is the most resource-intensive step in this -- module, so we try and avoid it where possible. For this reason, nil -- arguments are also memoized, in the nilArgs table. Also, we keep a record -- in the metatable of when pairs and ipairs have been called, so we do not -- run pairs and ipairs on the argument tables more than once. We also do -- not run ipairs on fargs and pargs if pairs has already been run, as all -- the arguments will already have been copied over. --]]  metatable.__index = function (t, key) --[[ -- Fetches an argument when the args table is indexed. First we check -- to see if the value is memoized, and if not we try and fetch it from -- the argument tables. When we check memoization, we need to check -- metaArgs before nilArgs, as both can be non-nil at the same time. -- If the argument is not present in metaArgs, we also check whether -- pairs has been run yet. If pairs has already been run, we return nil. -- This is because all the arguments will have already been copied into -- metaArgs by the mergeArgs function, meaning that any other arguments -- must be nil. --]] if type(key) == 'string' then key = options.translate[key] end local val = metaArgs[key] if val ~= nil then return val elseif metatable.donePairs or nilArgs[key] then return nil end for _, argTable in ipairs(argTables) do local argTableVal = tidyVal(key, argTable[key]) if argTableVal ~= nil then metaArgs[key] = argTableVal return argTableVal end end nilArgs[key] = 'h' return nil end  metatable.__newindex = function (t, key, val) -- This function is called when a module tries to add a new value to the -- args table, or tries to change an existing value. if type(key) == 'string' then key = options.translate[key] end if options.readOnly then error( 'không thể ghi vào khóa bảng đối số "' .. tostring(key) .. '"; bảng chỉ đọc', 2 ) elseif options.noOverwrite and args[key] ~= nil then error( 'không thể ghi vào khóa bảng đối số "' .. tostring(key) .. '"; không được phép ghi đè các đối số hiện có', 2 ) elseif val == nil then --[[ -- If the argument is to be overwritten with nil, we need to erase -- the value in metaArgs, so that __index, __pairs and __ipairs do -- not use a previous existing value, if present; and we also need -- to memoize the nil in nilArgs, so that the value isn't looked -- up in the argument tables if it is accessed again. --]] metaArgs[key] = nil nilArgs[key] = 'h' else metaArgs[key] = val end end  local function translatenext(invariant) local k, v = next(invariant.t, invariant.k) invariant.k = k if k == nil then return nil elseif type(k) ~= 'string' or not options.backtranslate then return k, v else local backtranslate = options.backtranslate[k] if backtranslate == nil then -- Skip this one. This is a tail call, so this won't cause stack overflow return translatenext(invariant) else return backtranslate, v end end end  metatable.__pairs = function () -- Called when pairs is run on the args table. if not metatable.donePairs then mergeArgs(argTables) metatable.donePairs = true end return translatenext, { t = metaArgs } end  local function inext(t, i) -- This uses our __index metamethod local v = t[i + 1] if v ~= nil then return i + 1, v end end  metatable.__ipairs = function (t) -- Called when ipairs is run on the args table. return inext, t, 0 end  return args end  return arguments 

Tags:

🔥 Trending searches on Wiki Tiếng Việt:

Cao BằngTừ Hán-ViệtSân bay quốc tế Long ThànhNgô QuyềnĐà NẵngĐiêu khắcQTrường Đại học Sư phạm Hà NộiPhùng Văn KhầuCác vị trí trong bóng đáTrung QuốcXuân DiệuMona LisaSinh sản vô tínhGoogle MapsKinh thành HuếMặt TrăngLiên QuânBọ Cạp (chiêm tinh)GallonLiên XôCác ngày lễ ở Việt NamĐại học Kinh tế Thành phố Hồ Chí MinhNhà HánKitô giáoDanh sách trận chung kết Cúp C1 châu Âu và UEFA Champions LeagueMặt TrờiĐạo giáoTô Ngọc ThanhNguyễn Hòa BìnhTrận Thành cổ Quảng TrịBà TriệuQuảng ĐôngLong châu truyền kỳĐờn ca tài tử Nam BộLê Khánh HảiTikTokẢ Rập Xê ÚtQuần đảo Hoàng SaKhổng TửNam CaoĐường cao tốc Diễn Châu – Bãi VọtGMMTVViêm da cơ địaTrần Đại QuangNam ĐịnhBan Bí thư Trung ương Đảng Cộng sản Việt NamẤn ĐộBạch LộcThuận TrịThánh địa Mỹ SơnPhong trào Dân chủ Đông Dương (1936–1939)Trùng KhánhLý Chiêu HoàngFansipanGấu trúc lớnTháp RùaNgân HàBộ Công an (Việt Nam)Mông CổAi CậpNhà ĐườngHuếĐài LoanChâu Nam CựcHKT (nhóm nhạc)Tiếng Trung QuốcRadio France InternationaleBất đẳng thức trung bình cộng và trung bình nhânChu vi hình trònBitcoinBuôn Ma ThuộtĐại dịch COVID-19 tại Việt NamNguyễn Nhật ÁnhQuốc hội Việt NamTito Vilanova🡆 More